7 objectPrototype = Object.prototype,
8 toString = Object.prototype.toString,
10 enumerablesTest = { toString: 1 },
13 if (typeof Ext === 'undefined') {
19 for (i in enumerablesTest) {
24 enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
25 'toLocaleString', 'toString', 'constructor'];
29 * An array containing extra enumerables for old browsers
32 Ext.enumerables = enumerables;
35 * Copies all the properties of config to the specified object.
36 * Note that if recursive merging and cloning without referencing the original objects / arrays is needed, use
37 * {@link Ext.Object#merge} instead.
38 * @param {Object} object The receiver of the properties
39 * @param {Object} config The source of the properties
40 * @param {Object} defaults A different object that will also be applied for default values
41 * @return {Object} returns obj
43 Ext.apply = function(object, config, defaults) {
45 Ext.apply(object, defaults);
48 if (object && config && typeof config === 'object') {
52 object[i] = config[i];
56 for (j = enumerables.length; j--;) {
58 if (config.hasOwnProperty(k)) {
59 object[k] = config[k];
68 Ext.buildSettings = Ext.apply({
71 }, Ext.buildSettings || {});
75 * A reusable empty function
77 emptyFn: function() {},
79 baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
82 * Copies all the properties of config to object if they don't already exist.
84 * @param {Object} object The receiver of the properties
85 * @param {Object} config The source of the properties
86 * @return {Object} returns obj
88 applyIf: function(object, config) {
92 for (property in config) {
93 if (object[property] === undefined) {
94 object[property] = config[property];
103 * Iterates either an array or an object. This method delegates to
104 * {@link Ext.Array#each Ext.Array.each} if the given value is iterable, and {@link Ext.Object#each Ext.Object.each} otherwise.
106 * @param {Object/Array} object The object or array to be iterated.
107 * @param {Function} fn The function to be called for each iteration. See and {@link Ext.Array#each Ext.Array.each} and
108 * {@link Ext.Object#each Ext.Object.each} for detailed lists of arguments passed to this function depending on the given object
109 * type that is being iterated.
110 * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
111 * Defaults to the object being iterated itself.
114 iterate: function(object, fn, scope) {
115 if (Ext.isEmpty(object)) {
119 if (scope === undefined) {
123 if (Ext.isIterable(object)) {
124 Ext.Array.each.call(Ext.Array, object, fn, scope);
127 Ext.Object.each.call(Ext.Object, object, fn, scope);
135 * This method deprecated. Use {@link Ext#define Ext.define} instead.
137 * @param {Function} superclass
138 * @param {Object} overrides
139 * @return {Function} The subclass constructor from the <tt>overrides</tt> parameter, or a generated one if not provided.
140 * @deprecated 4.0.0 Use {@link Ext#define Ext.define} instead
144 var objectConstructor = objectPrototype.constructor,
145 inlineOverrides = function(o) {
147 if (!o.hasOwnProperty(m)) {
154 return function(subclass, superclass, overrides) {
155 // First we check if the user passed in just the superClass with overrides
156 if (Ext.isObject(superclass)) {
157 overrides = superclass;
158 superclass = subclass;
159 subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
160 superclass.apply(this, arguments);
168 sourceMethod: 'extend',
169 msg: 'Attempting to extend from a class which has not been loaded on the page.'
174 // We create a new temporary class
175 var F = function() {},
176 subclassProto, superclassProto = superclass.prototype;
178 F.prototype = superclassProto;
179 subclassProto = subclass.prototype = new F();
180 subclassProto.constructor = subclass;
181 subclass.superclass = superclassProto;
183 if (superclassProto.constructor === objectConstructor) {
184 superclassProto.constructor = superclass;
187 subclass.override = function(overrides) {
188 Ext.override(subclass, overrides);
191 subclassProto.override = inlineOverrides;
192 subclassProto.proto = subclassProto;
194 subclass.override(overrides);
195 subclass.extend = function(o) {
196 return Ext.extend(subclass, o);
204 * Proxy to {@link Ext.Base#override}. Please refer {@link Ext.Base#override} for further details.
206 Ext.define('My.cool.Class', {
212 Ext.override(My.cool.Class, {
214 alert('About to say...');
216 this.callOverridden();
220 var cool = new My.cool.Class();
221 cool.sayHi(); // alerts 'About to say...'
224 * Please note that `this.callOverridden()` only works if the class was previously
225 * created with {@link Ext#define)
227 * @param {Object} cls The class to override
228 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
229 * containing one or more methods.
233 override: function(cls, overrides) {
234 if (cls.prototype.$className) {
235 return cls.override(overrides);
238 Ext.apply(cls.prototype, overrides);
243 // A full set of static methods to do type checking
247 * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default
248 * value (second argument) otherwise.
250 * @param {Mixed} value The value to test
251 * @param {Mixed} defaultValue The value to return if the original value is empty
252 * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
253 * @return {Mixed} value, if non-empty, else defaultValue
255 valueFrom: function(value, defaultValue, allowBlank){
256 return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
260 * Returns the type of the given variable in string format. List of possible values are:
262 * - `undefined`: If the given value is `undefined`
263 * - `null`: If the given value is `null`
264 * - `string`: If the given value is a string
265 * - `number`: If the given value is a number
266 * - `boolean`: If the given value is a boolean value
267 * - `date`: If the given value is a `Date` object
268 * - `function`: If the given value is a function reference
269 * - `object`: If the given value is an object
270 * - `array`: If the given value is an array
271 * - `regexp`: If the given value is a regular expression
272 * - `element`: If the given value is a DOM Element
273 * - `textnode`: If the given value is a DOM text node and contains something other than whitespace
274 * - `whitespace`: If the given value is a DOM text node and contains only whitespace
276 * @param {Mixed} value
280 typeOf: function(value) {
281 if (value === null) {
285 var type = typeof value;
287 if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
291 var typeToString = toString.call(value);
293 switch(typeToString) {
294 case '[object Array]':
296 case '[object Date]':
298 case '[object Boolean]':
300 case '[object Number]':
302 case '[object RegExp]':
306 if (type === 'function') {
310 if (type === 'object') {
311 if (value.nodeType !== undefined) {
312 if (value.nodeType === 3) {
313 return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
326 sourceMethod: 'typeOf',
327 msg: 'Failed to determine the type of the specified value "' + value + '". This is most likely a bug.'
333 * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if it is either:
337 * - a zero-length array
338 * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`)
340 * @param {Mixed} value The value to test
341 * @param {Boolean} allowEmptyString (optional) true to allow empty strings (defaults to false)
345 isEmpty: function(value, allowEmptyString) {
346 return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
350 * Returns true if the passed value is a JavaScript Array, false otherwise.
352 * @param {Mixed} target The target to test
356 isArray: ('isArray' in Array) ? Array.isArray : function(value) {
357 return toString.call(value) === '[object Array]';
361 * Returns true if the passed value is a JavaScript Date object, false otherwise.
362 * @param {Object} object The object to test
365 isDate: function(value) {
366 return toString.call(value) === '[object Date]';
370 * Returns true if the passed value is a JavaScript Object, false otherwise.
371 * @param {Mixed} value The value to test
375 isObject: (toString.call(null) === '[object Object]') ?
377 return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.nodeType === undefined;
380 return toString.call(value) === '[object Object]';
384 * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
385 * @param {Mixed} value The value to test
388 isPrimitive: function(value) {
389 var type = typeof value;
391 return type === 'string' || type === 'number' || type === 'boolean';
395 * Returns true if the passed value is a JavaScript Function, false otherwise.
396 * @param {Mixed} value The value to test
401 // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using
402 // Object.prorotype.toString (slower)
403 (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
404 return toString.call(value) === '[object Function]';
405 } : function(value) {
406 return typeof value === 'function';
410 * Returns true if the passed value is a number. Returns false for non-finite numbers.
411 * @param {Mixed} value The value to test
414 isNumber: function(value) {
415 return typeof value === 'number' && isFinite(value);
419 * Validates that a value is numeric.
420 * @param {Mixed} value Examples: 1, '1', '2.34'
421 * @return {Boolean} True if numeric, false otherwise
423 isNumeric: function(value) {
424 return !isNaN(parseFloat(value)) && isFinite(value);
428 * Returns true if the passed value is a string.
429 * @param {Mixed} value The value to test
432 isString: function(value) {
433 return typeof value === 'string';
437 * Returns true if the passed value is a boolean.
439 * @param {Mixed} value The value to test
442 isBoolean: function(value) {
443 return typeof value === 'boolean';
447 * Returns true if the passed value is an HTMLElement
448 * @param {Mixed} value The value to test
451 isElement: function(value) {
452 return value ? value.nodeType === 1 : false;
456 * Returns true if the passed value is a TextNode
457 * @param {Mixed} value The value to test
460 isTextNode: function(value) {
461 return value ? value.nodeName === "#text" : false;
465 * Returns true if the passed value is defined.
466 * @param {Mixed} value The value to test
469 isDefined: function(value) {
470 return typeof value !== 'undefined';
474 * Returns true if the passed value is iterable, false otherwise
475 * @param {Mixed} value The value to test
478 isIterable: function(value) {
479 return (value && typeof value !== 'string') ? value.length !== undefined : false;
486 * Clone almost any type of variable including array, object, DOM nodes and Date without keeping the old reference
487 * @param {Mixed} item The variable to clone
488 * @return {Mixed} clone
490 clone: function(item) {
491 if (item === null || item === undefined) {
496 // TODO proxy this to Ext.Element.clone to handle automatic id attribute changing
498 if (item.nodeType && item.cloneNode) {
499 return item.cloneNode(true);
502 var type = toString.call(item);
505 if (type === '[object Date]') {
506 return new Date(item.getTime());
509 var i, j, k, clone, key;
512 if (type === '[object Array]') {
518 clone[i] = Ext.clone(item[i]);
522 else if (type === '[object Object]' && item.constructor === Object) {
526 clone[key] = Ext.clone(item[key]);
530 for (j = enumerables.length; j--;) {
537 return clone || item;
542 * Generate a unique reference of Ext in the global scope, useful for sandboxing
544 getUniqueGlobalNamespace: function() {
545 var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
547 if (uniqueGlobalNamespace === undefined) {
551 uniqueGlobalNamespace = 'ExtSandbox' + (++i);
552 } while (Ext.global[uniqueGlobalNamespace] !== undefined);
554 Ext.global[uniqueGlobalNamespace] = Ext;
555 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
558 return uniqueGlobalNamespace;
564 functionFactory: function() {
565 var args = Array.prototype.slice.call(arguments);
567 if (args.length > 0) {
568 args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
569 args[args.length - 1];
572 return Function.prototype.constructor.apply(Function.prototype, args);
577 * Old alias to {@link Ext#typeOf}
578 * @deprecated 4.0.0 Use {@link Ext#typeOf} instead
581 Ext.type = Ext.typeOf;