    // @tag foundation,core
    // @define Ext

    /**
     * @class Ext
     * @singleton
     */
    var Ext = Ext || {};
    Ext._startTime = new Date().getTime();
    (function() {
        var global = this,
            objectPrototype = Object.prototype,
            toString = objectPrototype.toString,
            enumerables = true,
            enumerablesTest = {toString: 1},
            emptyFn = function () {},
            // This is the "$previous" method of a hook function on an instance. When called, it
            // calls through the class prototype by the name of the called method.
            callOverrideParent = function () {
                var method = callOverrideParent.caller.caller; // skip callParent (our caller)
                return method.$owner.prototype[method.$name].apply(this, arguments);
            },
            i,
            nonWhitespaceRe = /\S/,
            ExtApp,
            iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|HTML\s+document\.all\s+class)\]/;

        Function.prototype.$extIsFunction = true;

        Ext.global = global;

        for (i in enumerablesTest) {
            enumerables = null;
        }

        if (enumerables) {
            enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
                           'toLocaleString', 'toString', 'constructor'];
        }

        /**
         * An array containing extra enumerables for old browsers
         * @property {String[]}
         */
        Ext.enumerables = enumerables;

        /**
         * Copies all the properties of config to the specified object.
         * Note that if recursive merging and cloning without referencing the original objects / arrays is needed, use
         * {@link Ext.Object#merge} instead.
         * @param {Object} object The receiver of the properties
         * @param {Object} config The source of the properties
         * @param {Object} [defaults] A different object that will also be applied for default values
         * @return {Object} returns obj
         */
        Ext.apply = function(object, config, defaults) {
            if (defaults) {
                Ext.apply(object, defaults);
            }

            if (object && config && typeof config === 'object') {
                var i, j, k;

                for (i in config) {
                    object[i] = config[i];
                }

                if (enumerables) {
                    for (j = enumerables.length; j--;) {
                        k = enumerables[j];
                        if (config.hasOwnProperty(k)) {
                            object[k] = config[k];
                        }
                    }
                }
            }

            return object;
        };

        Ext.buildSettings = Ext.apply({
            baseCSSPrefix: 'x-'
        }, Ext.buildSettings || {});

        Ext.apply(Ext, {

            /**
             * @property {String} [name='Ext']
             * <p>The name of the property in the global namespace (The <code>window</code> in browser environments) which refers to the current instance of Ext.</p>
             * <p>This is usually <code>"Ext"</code>, but if a sandboxed build of ExtJS is being used, this will be an alternative name.</p>
             * <p>If code is being generated for use by <code>eval</code> or to create a <code>new Function</code>, and the global instance
             * of Ext must be referenced, this is the name that should be built into the code.</p>
             */
            name: Ext.sandboxName || 'Ext',

            /**
             * @property {Function}
             * A reusable empty function
             */
            emptyFn: emptyFn,

            /**
             * A reusable identity function. The function will always return the first argument, unchanged.
             */
            identityFn: function(o) {
                return o;
            },

            /**
             * A zero length string which will pass a truth test. Useful for passing to methods
             * which use a truth test to reject <i>falsy</i> values where a string value must be cleared.
             */
            emptyString: new String(),

            baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,

            /**
             * Copies all the properties of config to object if they don't already exist.
             * @param {Object} object The receiver of the properties
             * @param {Object} config The source of the properties
             * @return {Object} returns obj
             */
            applyIf: function(object, config) {
                var property;

                if (object) {
                    for (property in config) {
                        if (object[property] === undefined) {
                            object[property] = config[property];
                        }
                    }
                }

                return object;
            },

            /**
             * Iterates either an array or an object. This method delegates to
             * {@link Ext.Array#each Ext.Array.each} if the given value is iterable, and {@link Ext.Object#each Ext.Object.each} otherwise.
             *
             * @param {Object/Array} object The object or array to be iterated.
             * @param {Function} fn The function to be called for each iteration. See and {@link Ext.Array#each Ext.Array.each} and
             * {@link Ext.Object#each Ext.Object.each} for detailed lists of arguments passed to this function depending on the given object
             * type that is being iterated.
             * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
             * Defaults to the object being iterated itself.
             * @markdown
             */
            iterate: function(object, fn, scope) {
                if (Ext.isEmpty(object)) {
                    return;
                }

                if (scope === undefined) {
                    scope = object;
                }

                if (Ext.isIterable(object)) {
                    Ext.Array.each.call(Ext.Array, object, fn, scope);
                }
                else {
                    Ext.Object.each.call(Ext.Object, object, fn, scope);
                }
            }
        });

        Ext.apply(Ext, {

            /**
             * This method deprecated. Use {@link Ext#define Ext.define} instead.
             * @method
             * @param {Function} superclass
             * @param {Object} overrides
             * @return {Function} The subclass constructor from the <tt>overrides</tt> parameter, or a generated one if not provided.
             * @deprecated 4.0.0 Use {@link Ext#define Ext.define} instead
             */
            extend: (function() {
                // inline overrides
                var objectConstructor = objectPrototype.constructor,
                    inlineOverrides = function(o) {
                    for (var m in o) {
                        if (!o.hasOwnProperty(m)) {
                            continue;
                        }
                        this[m] = o[m];
                    }
                };

                return function(subclass, superclass, overrides) {
                    // First we check if the user passed in just the superClass with overrides
                    if (Ext.isObject(superclass)) {
                        overrides = superclass;
                        superclass = subclass;
                        subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
                            superclass.apply(this, arguments);
                        };
                    }

                    //<debug>
                    if (!superclass) {
                        Ext.Error.raise({
                            sourceClass: 'Ext',
                            sourceMethod: 'extend',
                            msg: 'Attempting to extend from a class which has not been loaded on the page.'
                        });
                    }
                    //</debug>

                    // We create a new temporary class
                    var F = function() {},
                        subclassProto, superclassProto = superclass.prototype;

                    F.prototype = superclassProto;
                    subclassProto = subclass.prototype = new F();
                    subclassProto.constructor = subclass;
                    subclass.superclass = superclassProto;

                    if (superclassProto.constructor === objectConstructor) {
                        superclassProto.constructor = superclass;
                    }

                    subclass.override = function(overrides) {
                        Ext.override(subclass, overrides);
                    };

                    subclassProto.override = inlineOverrides;
                    subclassProto.proto = subclassProto;

                    subclass.override(overrides);
                    subclass.extend = function(o) {
                        return Ext.extend(subclass, o);
                    };

                    return subclass;
                };
            }()),

            /**
             * Overrides members of the specified `target` with the given values.
             *
             * If the `target` is a class declared using {@link Ext#define Ext.define}, the
             * `override` method of that class is called (see {@link Ext.Base#override}) given
             * the `overrides`.
             *
             * If the `target` is a function, it is assumed to be a constructor and the contents
             * of `overrides` are applied to its `prototype` using {@link Ext#apply Ext.apply}.
             *
             * If the `target` is an instance of a class declared using {@link Ext#define Ext.define},
             * the `overrides` are applied to only that instance. In this case, methods are
             * specially processed to allow them to use {@link Ext.Base#callParent}.
             *
             *      var panel = new Ext.Panel({ ... });
             *
             *      Ext.override(panel, {
             *          initComponent: function () {
             *              // extra processing...
             *
             *              this.callParent();
             *          }
             *      });
             *
             * If the `target` is none of these, the `overrides` are applied to the `target`
             * using {@link Ext#apply Ext.apply}.
             *
             * Please refer to {@link Ext#define Ext.define} and {@link Ext.Base#override} for
             * further details.
             *
             * @param {Object} target The target to override.
             * @param {Object} overrides The properties to add or replace on `target`.
             * @method override
             */
            override: function (target, overrides) {
                if (target.$isClass) {
                    target.override(overrides);
                } else if (typeof target == 'function') {
                    Ext.apply(target.prototype, overrides);
                } else {
                    var owner = target.self,
                        name, value;

                    if (owner && owner.$isClass) { // if (instance of Ext.define'd class)
                        for (name in overrides) {
                            if (overrides.hasOwnProperty(name)) {
                                value = overrides[name];

                                if (typeof value == 'function') {
                                    //<debug>
                                    if (owner.$className) {
                                        value.displayName = owner.$className + '#' + name;
                                    }
                                    //</debug>

                                    value.$name = name;
                                    value.$owner = owner;
                                    value.$previous = target.hasOwnProperty(name)
                                        ? target[name] // already hooked, so call previous hook
                                        : callOverrideParent; // calls by name on prototype
                                }

                                target[name] = value;
                            }
                        }
                    } else {
                        Ext.apply(target, overrides);
                    }
                }

                return target;
            }
        });

        // A full set of static methods to do type checking
        Ext.apply(Ext, {

            /**
             * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default
             * value (second argument) otherwise.
             *
             * @param {Object} value The value to test
             * @param {Object} defaultValue The value to return if the original value is empty
             * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
             * @return {Object} value, if non-empty, else defaultValue
             */
            valueFrom: function(value, defaultValue, allowBlank){
                return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
            },

            /**
             * Returns the type of the given variable in string format. List of possible values are:
             *
             * - `undefined`: If the given value is `undefined`
             * - `null`: If the given value is `null`
             * - `string`: If the given value is a string
             * - `number`: If the given value is a number
             * - `boolean`: If the given value is a boolean value
             * - `date`: If the given value is a `Date` object
             * - `function`: If the given value is a function reference
             * - `object`: If the given value is an object
             * - `array`: If the given value is an array
             * - `regexp`: If the given value is a regular expression
             * - `element`: If the given value is a DOM Element
             * - `textnode`: If the given value is a DOM text node and contains something other than whitespace
             * - `whitespace`: If the given value is a DOM text node and contains only whitespace
             *
             * @param {Object} value
             * @return {String}
             * @markdown
             */
            typeOf: function(value) {
                var type,
                    typeToString;

                if (value === null) {
                    return 'null';
                }

                type = typeof value;

                if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
                    return type;
                }

                typeToString = toString.call(value);

                switch(typeToString) {
                    case '[object Array]':
                        return 'array';
                    case '[object Date]':
                        return 'date';
                    case '[object Boolean]':
                        return 'boolean';
                    case '[object Number]':
                        return 'number';
                    case '[object RegExp]':
                        return 'regexp';
                }

                if (type === 'function') {
                    return 'function';
                }

                if (type === 'object') {
                    if (value.nodeType !== undefined) {
                        if (value.nodeType === 3) {
                            return (nonWhitespaceRe).test(value.nodeValue) ? 'textnode' : 'whitespace';
                        }
                        else {
                            return 'element';
                        }
                    }

                    return 'object';
                }

                //<debug error>
                Ext.Error.raise({
                    sourceClass: 'Ext',
                    sourceMethod: 'typeOf',
                    msg: 'Failed to determine the type of the specified value "' + value + '". This is most likely a bug.'
                });
                //</debug>
            },

            /**
             * Coerces the first value if possible so that it is comparable to the second value.
             *
             * Coercion only works between the basic atomic data types String, Boolean, Number, Date, null and undefined.
             *
             * Numbers and numeric strings are coerced to Dates using the value as the millisecond era value.
             *
             * Strings are coerced to Dates by parsing using the {@link Ext.Date#defaultFormat defaultFormat}.
             *
             * For example
             *
             *     Ext.coerce('false', true);
             *
             * returns the boolean value `false` because the second parameter is of type `Boolean`.
             *
             * @param {Mixed} from The value to coerce
             * @param {Mixed} to The value it must be compared against
             * @return The coerced value.
             */
            coerce: function(from, to) {
                var fromType = Ext.typeOf(from),
                    toType = Ext.typeOf(to),
                    isString = typeof from === 'string';

                if (fromType !== toType) {
                    switch (toType) {
                        case 'string':
                            return String(from);
                        case 'number':
                            return Number(from);
                        case 'boolean':
                            return isString && (!from || from === 'false') ? false : Boolean(from);
                        case 'null':
                            return isString && (!from || from === 'null') ? null : from;
                        case 'undefined':
                            return isString && (!from || from === 'undefined') ? undefined : from;
                        case 'date':
                            return isString && isNaN(from) ? Ext.Date.parse(from, Ext.Date.defaultFormat) : Date(Number(from));
                    }
                }
                return from;
            },

            /**
             * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if it is either:
             *
             * - `null`
             * - `undefined`
             * - a zero-length array
             * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`)
             *
             * @param {Object} value The value to test
             * @param {Boolean} allowEmptyString (optional) true to allow empty strings (defaults to false)
             * @return {Boolean}
             * @markdown
             */
            isEmpty: function(value, allowEmptyString) {
                return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
            },

            /**
             * Returns true if the passed value is a JavaScript Array, false otherwise.
             *
             * @param {Object} target The target to test
             * @return {Boolean}
             * @method
             */
            isArray: ('isArray' in Array) ? Array.isArray : function(value) {
                return toString.call(value) === '[object Array]';
            },

            /**
             * Returns true if the passed value is a JavaScript Date object, false otherwise.
             * @param {Object} object The object to test
             * @return {Boolean}
             */
            isDate: function(value) {
                return toString.call(value) === '[object Date]';
            },

            /**
             * Returns true if the passed value is a JavaScript Object, false otherwise.
             * @param {Object} value The value to test
             * @return {Boolean}
             * @method
             */
            isObject: (toString.call(null) === '[object Object]') ?
            function(value) {
                // check ownerDocument here as well to exclude DOM nodes
                return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
            } :
            function(value) {
                return toString.call(value) === '[object Object]';
            },

            /**
             * @private
             */
            isSimpleObject: function(value) {
                return value instanceof Object && value.constructor === Object;
            },
            /**
             * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isPrimitive: function(value) {
                var type = typeof value;

                return type === 'string' || type === 'number' || type === 'boolean';
            },

            /**
             * Returns true if the passed value is a JavaScript Function, false otherwise.
             * @param {Object} value The value to test
             * @return {Boolean}
             * @method
             */
            isFunction: function(value) {
                return !!(value && value.$extIsFunction);
            },

            /**
             * Returns true if the passed value is a number. Returns false for non-finite numbers.
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isNumber: function(value) {
                return typeof value === 'number' && isFinite(value);
            },

            /**
             * Validates that a value is numeric.
             * @param {Object} value Examples: 1, '1', '2.34'
             * @return {Boolean} True if numeric, false otherwise
             */
            isNumeric: function(value) {
                return !isNaN(parseFloat(value)) && isFinite(value);
            },

            /**
             * Returns true if the passed value is a string.
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isString: function(value) {
                return typeof value === 'string';
            },

            /**
             * Returns true if the passed value is a boolean.
             *
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isBoolean: function(value) {
                return typeof value === 'boolean';
            },

            /**
             * Returns true if the passed value is an HTMLElement
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isElement: function(value) {
                return value ? value.nodeType === 1 : false;
            },

            /**
             * Returns true if the passed value is a TextNode
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isTextNode: function(value) {
                return value ? value.nodeName === "#text" : false;
            },

            /**
             * Returns true if the passed value is defined.
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isDefined: function(value) {
                return typeof value !== 'undefined';
            },

            /**
             * Returns `true` if the passed value is iterable, that is, if elements of it are addressable using array
             * notation with numeric indices, `false` otherwise.
             *
             * Arrays and function `arguments` objects are iterable. Also HTML collections such as `NodeList` and `HTMLCollection'
             * are iterable.
             *
             * @param {Object} value The value to test
             * @return {Boolean}
             */
            isIterable: function(value) {
                // To be iterable, the object must have a numeric length property and must not be a string or function.
                if (!value || typeof value.length !== 'number' || typeof value === 'string' || value.$extIsFunction) {
                    return false;
                }

                // Certain "standard" collections in IE (such as document.images) do not offer the correct
                // Javascript Object interface; specifically, they lack the propertyIsEnumerable method.
                // And the item property while it does exist is not typeof "function"
                if (!value.propertyIsEnumerable) {
                    return !!value.item;
                }

                // If it is a regular, interrogatable JS object (not an IE ActiveX object), then...
                // If it has its own property called "length", but not enumerable, it's iterable
                if (value.hasOwnProperty('length') && !value.propertyIsEnumerable('length')) {
                    return true;
                }

                // Test against whitelist which includes known iterable collection types
                return iterableRe.test(toString.call(value));
            }
        });

        Ext.apply(Ext, {

            /**
             * Clone simple variables including array, {}-like objects, DOM nodes and Date without keeping the old reference.
             * A reference for the object itself is returned if it's not a direct decendant of Object. For model cloning,
             * see {@link Ext.data.Model#copy Model.copy}.
             *
             * @param {Object} item The variable to clone
             * @return {Object} clone
             */
            clone: function(item) {
                var type,
                    i,
                    j,
                    k,
                    clone,
                    key;

                if (item === null || item === undefined) {
                    return item;
                }

                // DOM nodes
                // TODO proxy this to Ext.Element.clone to handle automatic id attribute changing
                // recursively
                if (item.nodeType && item.cloneNode) {
                    return item.cloneNode(true);
                }

                type = toString.call(item);

                // Date
                if (type === '[object Date]') {
                    return new Date(item.getTime());
                }

                // Array
                if (type === '[object Array]') {
                    i = item.length;

                    clone = [];

                    while (i--) {
                        clone[i] = Ext.clone(item[i]);
                    }
                }
                // Object
                else if (type === '[object Object]' && item.constructor === Object) {
                    clone = {};

                    for (key in item) {
                        clone[key] = Ext.clone(item[key]);
                    }

                    if (enumerables) {
                        for (j = enumerables.length; j--;) {
                            k = enumerables[j];
                            if (item.hasOwnProperty(k)) {
                                clone[k] = item[k];
                            }
                        }
                    }
                }

                return clone || item;
            },

            /**
             * @private
             * Generate a unique reference of Ext in the global scope, useful for sandboxing
             */
            getUniqueGlobalNamespace: function() {
                var uniqueGlobalNamespace = this.uniqueGlobalNamespace,
                    i;

                if (uniqueGlobalNamespace === undefined) {
                    i = 0;

                    do {
                        uniqueGlobalNamespace = 'ExtBox' + (++i);
                    } while (Ext.global[uniqueGlobalNamespace] !== undefined);

                    Ext.global[uniqueGlobalNamespace] = Ext;
                    this.uniqueGlobalNamespace = uniqueGlobalNamespace;
                }

                return uniqueGlobalNamespace;
            },

            /**
             * @private
             */
            functionFactoryCache: {},

            cacheableFunctionFactory: function() {
                var me = this,
                    args = Array.prototype.slice.call(arguments),
                    cache = me.functionFactoryCache,
                    idx, fn, ln;

                 if (Ext.isSandboxed) {
                    ln = args.length;
                    if (ln > 0) {
                        ln--;
                        args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];
                    }
                }
                idx = args.join('');
                fn = cache[idx];
                if (!fn) {
                    fn = Function.prototype.constructor.apply(Function.prototype, args);

                    cache[idx] = fn;
                }
                return fn;
            },

            functionFactory: function() {
                var me = this,
                    args = Array.prototype.slice.call(arguments),
                    ln;

                if (Ext.isSandboxed) {
                    ln = args.length;
                    if (ln > 0) {
                        ln--;
                        args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];
                    }
                }

                return Function.prototype.constructor.apply(Function.prototype, args);
            },

            /**
             * @private
             * @property
             */
            Logger: {
                verbose: emptyFn,
                log: emptyFn,
                info: emptyFn,
                warn: emptyFn,
                error: function(message) {
                    throw new Error(message);
                },
                deprecate: emptyFn
            }
        });

        /**
         * Old alias to {@link Ext#typeOf}
         * @deprecated 4.0.0 Use {@link Ext#typeOf} instead
         * @method
         * @inheritdoc Ext#typeOf
         */
        Ext.type = Ext.typeOf;

        // When using Cmd optimizations, the namespace Ext.app may already be defined
        // by this point since it's done up front by the tool. Check if app already
        // exists before overwriting it.
        ExtApp = Ext.app;
        if (!ExtApp) {
            ExtApp = Ext.app = {};
        }
        Ext.apply(ExtApp, {
            namespaces: {},

            /**
            * @private
            */
            collectNamespaces: function(paths) {
                var namespaces = Ext.app.namespaces,
                    path;

                for (path in paths) {
                    if (paths.hasOwnProperty(path)) {
                        namespaces[path] = true;
                    }
                }
            },

            /**
            * Adds namespace(s) to known list.
            *
            * @param {String/String[]} namespace
            */
            addNamespaces: function(ns) {
                var namespaces = Ext.app.namespaces,
                    i, l;

                if (!Ext.isArray(ns)) {
                    ns = [ns];
                }

                for (i = 0, l = ns.length; i < l; i++) {
                    namespaces[ns[i]] = true;
                }
            },

            /**
            * @private Clear all namespaces from known list.
            */
            clearNamespaces: function() {
                Ext.app.namespaces = {};
            },

            /**
            * Get namespace prefix for a class name.
            *
            * @param {String} className
            *
            * @return {String} Namespace prefix if it's known, otherwise undefined
            */
            getNamespace: function(className) {
                var namespaces    = Ext.app.namespaces,
                    deepestPrefix = '',
                    prefix;

                for (prefix in namespaces) {
                    if (namespaces.hasOwnProperty(prefix)    &&
                        prefix.length > deepestPrefix.length &&
                        (prefix + '.' === className.substring(0, prefix.length + 1))) {
                        deepestPrefix = prefix;
                    }
                }

                return deepestPrefix === '' ? undefined : deepestPrefix;
            }
        });
    }());

    /*
     * This method evaluates the given code free of any local variable. In some browsers this
     * will be at global scope, in others it will be in a function.
     * @parma {String} code The code to evaluate.
     * @private
     * @method
     */
    Ext.globalEval = Ext.global.execScript
        ? function(code) {
            execScript(code);
        }
        : function($$code) {
            // IMPORTANT: because we use eval we cannot place this in the above function or it
            // will break the compressor's ability to rename local variables...
            (function(){
                // This var should not be replaced by the compressor. We need to do this so
                // that Ext refers to the global Ext, if we're sandboxing it may
                // refer to the local instance inside the closure
                var Ext = this.Ext;
                eval($$code);
            }());
        };