//@tag foundation,core //@define Ext /** * @class Ext * @singleton */ (function() { var global = this, objectPrototype = Object.prototype, toString = objectPrototype.toString, enumerables = true, enumerablesTest = { toString: 1 }, emptyFn = function(){}, i; if (typeof Ext === 'undefined') { global.Ext = {}; } 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-', scopeResetCSS: false }, Ext.buildSettings || {}); Ext.apply(Ext, { /** * @property {Function} * A reusable empty function */ emptyFn: emptyFn, 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. */ 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 `overrides` parameter, or a generated one if not provided. * @deprecated 2.0.0 Please 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; }; }(), /** * Proxy to {@link Ext.Base#override}. Please refer {@link Ext.Base#override} for further details. * * @param {Object} cls The class to override * @param {Object} overrides The properties to add to `origClass`. This should be specified as an object literal * containing one or more properties. * @method override * @deprecated 2.0.0 Please use {@link Ext#define Ext.define} instead. */ override: function(cls, overrides) { if (cls.$isClass) { return cls.override(overrides); } else { Ext.apply(cls.prototype, overrides); } } }); // 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=false] (optional) `true` to allow zero length strings to qualify as non-empty. * @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} */ typeOf: function(value) { if (value === null) { return 'null'; } var type = typeof value; if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') { return type; } var 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 (/\S/).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> }, /** * 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=false] (optional) `true` to allow empty strings. * @return {Boolean} */ 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 String that matches the MS Date JSON encoding format * @param {String} value The string to test * @return {Boolean} */ isMSDate: function(value) { if (!Ext.isString(value)) { return false; } else { return value.match("\\\\?/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\\\?/") !== null; } }, /** * 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: // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using // Object.prorotype.toString (slower) (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) { return toString.call(value) === '[object Function]'; } : function(value) { return typeof value === 'function'; }, /** * 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, `false` otherwise. * @param {Object} value The value to test. * @return {Boolean} */ isIterable: function(value) { return (value && typeof value !== 'string') ? value.length !== undefined : false; } }); Ext.apply(Ext, { /** * Clone almost any type of variable including array, object, DOM nodes and Date without keeping the old reference. * @param {Object} item The variable to clone. * @return {Object} clone */ clone: function(item) { if (item === null || item === undefined) { return item; } // DOM nodes if (item.nodeType && item.cloneNode) { return item.cloneNode(true); } // Strings var type = toString.call(item); // Dates if (type === '[object Date]') { return new Date(item.getTime()); } var i, j, k, clone, key; // Arrays if (type === '[object Array]') { i = item.length; clone = []; while (i--) { clone[i] = Ext.clone(item[i]); } } // Objects 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]; 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; if (uniqueGlobalNamespace === undefined) { var i = 0; do { uniqueGlobalNamespace = 'ExtBox' + (++i); } while (Ext.global[uniqueGlobalNamespace] !== undefined); Ext.global[uniqueGlobalNamespace] = Ext; this.uniqueGlobalNamespace = uniqueGlobalNamespace; } return uniqueGlobalNamespace; }, /** * @private */ functionFactory: function() { var args = Array.prototype.slice.call(arguments), ln = args.length; if (ln > 0) { args[ln - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' + args[ln - 1]; } return Function.prototype.constructor.apply(Function.prototype, args); }, /** * @private */ globalEval: ('execScript' in global) ? function(code) { global.execScript(code) } : function(code) { (function(){ eval(code); })(); } //<feature logger> /** * @private * @property */ ,Logger: { log: function(message, priority) { if ('console' in global) { if (!priority || !(priority in global.console)) { priority = 'log'; } message = '[' + priority.toUpperCase() + '] ' + message; global.console[priority](message); } }, verbose: function(message) { this.log(message, 'verbose'); }, info: function(message) { this.log(message, 'info'); }, warn: function(message) { this.log(message, 'warn'); }, error: function(message) { throw new Error(message); }, deprecate: function(message) { this.log(message, 'warn'); } } //</feature> }); /** * Old alias to {@link Ext#typeOf}. * @deprecated 2.0.0 Please use {@link Ext#typeOf} instead. * @method * @alias Ext#typeOf */ Ext.type = Ext.typeOf; })();