/ext-4.0.7/ext-all-debug-w-comments.js
JavaScript | 14030 lines | 7599 code | 1129 blank | 5302 comment | 1308 complexity | cd31a3bae62ba15b08ea7e8779ed7476 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/*
2
3This file is part of Ext JS 4
4
5Copyright (c) 2011 Sencha Inc
6
7Contact: http://www.sencha.com/contact
8
9GNU General Public License Usage
10This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14*/
15/**
16 * @class Ext
17 * @singleton
18 */
19(function() {
20 var global = this,
21 objectPrototype = Object.prototype,
22 toString = objectPrototype.toString,
23 enumerables = true,
24 enumerablesTest = { toString: 1 },
25 i;
26
27 if (typeof Ext === 'undefined') {
28 global.Ext = {};
29 }
30
31 Ext.global = global;
32
33 for (i in enumerablesTest) {
34 enumerables = null;
35 }
36
37 if (enumerables) {
38 enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
39 'toLocaleString', 'toString', 'constructor'];
40 }
41
42 /**
43 * An array containing extra enumerables for old browsers
44 * @property {String[]}
45 */
46 Ext.enumerables = enumerables;
47
48 /**
49 * Copies all the properties of config to the specified object.
50 * Note that if recursive merging and cloning without referencing the original objects / arrays is needed, use
51 * {@link Ext.Object#merge} instead.
52 * @param {Object} object The receiver of the properties
53 * @param {Object} config The source of the properties
54 * @param {Object} defaults A different object that will also be applied for default values
55 * @return {Object} returns obj
56 */
57 Ext.apply = function(object, config, defaults) {
58 if (defaults) {
59 Ext.apply(object, defaults);
60 }
61
62 if (object && config && typeof config === 'object') {
63 var i, j, k;
64
65 for (i in config) {
66 object[i] = config[i];
67 }
68
69 if (enumerables) {
70 for (j = enumerables.length; j--;) {
71 k = enumerables[j];
72 if (config.hasOwnProperty(k)) {
73 object[k] = config[k];
74 }
75 }
76 }
77 }
78
79 return object;
80 };
81
82 Ext.buildSettings = Ext.apply({
83 baseCSSPrefix: 'x-',
84 scopeResetCSS: false
85 }, Ext.buildSettings || {});
86
87 Ext.apply(Ext, {
88 /**
89 * A reusable empty function
90 */
91 emptyFn: function() {},
92
93 baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,
94
95 /**
96 * Copies all the properties of config to object if they don't already exist.
97 * @param {Object} object The receiver of the properties
98 * @param {Object} config The source of the properties
99 * @return {Object} returns obj
100 */
101 applyIf: function(object, config) {
102 var property;
103
104 if (object) {
105 for (property in config) {
106 if (object[property] === undefined) {
107 object[property] = config[property];
108 }
109 }
110 }
111
112 return object;
113 },
114
115 /**
116 * Iterates either an array or an object. This method delegates to
117 * {@link Ext.Array#each Ext.Array.each} if the given value is iterable, and {@link Ext.Object#each Ext.Object.each} otherwise.
118 *
119 * @param {Object/Array} object The object or array to be iterated.
120 * @param {Function} fn The function to be called for each iteration. See and {@link Ext.Array#each Ext.Array.each} and
121 * {@link Ext.Object#each Ext.Object.each} for detailed lists of arguments passed to this function depending on the given object
122 * type that is being iterated.
123 * @param {Object} scope (Optional) The scope (`this` reference) in which the specified function is executed.
124 * Defaults to the object being iterated itself.
125 * @markdown
126 */
127 iterate: function(object, fn, scope) {
128 if (Ext.isEmpty(object)) {
129 return;
130 }
131
132 if (scope === undefined) {
133 scope = object;
134 }
135
136 if (Ext.isIterable(object)) {
137 Ext.Array.each.call(Ext.Array, object, fn, scope);
138 }
139 else {
140 Ext.Object.each.call(Ext.Object, object, fn, scope);
141 }
142 }
143 });
144
145 Ext.apply(Ext, {
146
147 /**
148 * This method deprecated. Use {@link Ext#define Ext.define} instead.
149 * @method
150 * @param {Function} superclass
151 * @param {Object} overrides
152 * @return {Function} The subclass constructor from the <tt>overrides</tt> parameter, or a generated one if not provided.
153 * @deprecated 4.0.0 Use {@link Ext#define Ext.define} instead
154 */
155 extend: function() {
156 // inline overrides
157 var objectConstructor = objectPrototype.constructor,
158 inlineOverrides = function(o) {
159 for (var m in o) {
160 if (!o.hasOwnProperty(m)) {
161 continue;
162 }
163 this[m] = o[m];
164 }
165 };
166
167 return function(subclass, superclass, overrides) {
168 // First we check if the user passed in just the superClass with overrides
169 if (Ext.isObject(superclass)) {
170 overrides = superclass;
171 superclass = subclass;
172 subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
173 superclass.apply(this, arguments);
174 };
175 }
176
177
178 // We create a new temporary class
179 var F = function() {},
180 subclassProto, superclassProto = superclass.prototype;
181
182 F.prototype = superclassProto;
183 subclassProto = subclass.prototype = new F();
184 subclassProto.constructor = subclass;
185 subclass.superclass = superclassProto;
186
187 if (superclassProto.constructor === objectConstructor) {
188 superclassProto.constructor = superclass;
189 }
190
191 subclass.override = function(overrides) {
192 Ext.override(subclass, overrides);
193 };
194
195 subclassProto.override = inlineOverrides;
196 subclassProto.proto = subclassProto;
197
198 subclass.override(overrides);
199 subclass.extend = function(o) {
200 return Ext.extend(subclass, o);
201 };
202
203 return subclass;
204 };
205 }(),
206
207 /**
208 * Proxy to {@link Ext.Base#override}. Please refer {@link Ext.Base#override} for further details.
209
210 Ext.define('My.cool.Class', {
211 sayHi: function() {
212 alert('Hi!');
213 }
214 }
215
216 Ext.override(My.cool.Class, {
217 sayHi: function() {
218 alert('About to say...');
219
220 this.callOverridden();
221 }
222 });
223
224 var cool = new My.cool.Class();
225 cool.sayHi(); // alerts 'About to say...'
226 // alerts 'Hi!'
227
228 * Please note that `this.callOverridden()` only works if the class was previously
229 * created with {@link Ext#define)
230 *
231 * @param {Object} cls The class to override
232 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
233 * containing one or more methods.
234 * @method override
235 * @markdown
236 */
237 override: function(cls, overrides) {
238 if (cls.prototype.$className) {
239 return cls.override(overrides);
240 }
241 else {
242 Ext.apply(cls.prototype, overrides);
243 }
244 }
245 });
246
247 // A full set of static methods to do type checking
248 Ext.apply(Ext, {
249
250 /**
251 * Returns the given value itself if it's not empty, as described in {@link Ext#isEmpty}; returns the default
252 * value (second argument) otherwise.
253 *
254 * @param {Object} value The value to test
255 * @param {Object} defaultValue The value to return if the original value is empty
256 * @param {Boolean} allowBlank (optional) true to allow zero length strings to qualify as non-empty (defaults to false)
257 * @return {Object} value, if non-empty, else defaultValue
258 */
259 valueFrom: function(value, defaultValue, allowBlank){
260 return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
261 },
262
263 /**
264 * Returns the type of the given variable in string format. List of possible values are:
265 *
266 * - `undefined`: If the given value is `undefined`
267 * - `null`: If the given value is `null`
268 * - `string`: If the given value is a string
269 * - `number`: If the given value is a number
270 * - `boolean`: If the given value is a boolean value
271 * - `date`: If the given value is a `Date` object
272 * - `function`: If the given value is a function reference
273 * - `object`: If the given value is an object
274 * - `array`: If the given value is an array
275 * - `regexp`: If the given value is a regular expression
276 * - `element`: If the given value is a DOM Element
277 * - `textnode`: If the given value is a DOM text node and contains something other than whitespace
278 * - `whitespace`: If the given value is a DOM text node and contains only whitespace
279 *
280 * @param {Object} value
281 * @return {String}
282 * @markdown
283 */
284 typeOf: function(value) {
285 if (value === null) {
286 return 'null';
287 }
288
289 var type = typeof value;
290
291 if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
292 return type;
293 }
294
295 var typeToString = toString.call(value);
296
297 switch(typeToString) {
298 case '[object Array]':
299 return 'array';
300 case '[object Date]':
301 return 'date';
302 case '[object Boolean]':
303 return 'boolean';
304 case '[object Number]':
305 return 'number';
306 case '[object RegExp]':
307 return 'regexp';
308 }
309
310 if (type === 'function') {
311 return 'function';
312 }
313
314 if (type === 'object') {
315 if (value.nodeType !== undefined) {
316 if (value.nodeType === 3) {
317 return (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
318 }
319 else {
320 return 'element';
321 }
322 }
323
324 return 'object';
325 }
326
327 },
328
329 /**
330 * Returns true if the passed value is empty, false otherwise. The value is deemed to be empty if it is either:
331 *
332 * - `null`
333 * - `undefined`
334 * - a zero-length array
335 * - a zero-length string (Unless the `allowEmptyString` parameter is set to `true`)
336 *
337 * @param {Object} value The value to test
338 * @param {Boolean} allowEmptyString (optional) true to allow empty strings (defaults to false)
339 * @return {Boolean}
340 * @markdown
341 */
342 isEmpty: function(value, allowEmptyString) {
343 return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
344 },
345
346 /**
347 * Returns true if the passed value is a JavaScript Array, false otherwise.
348 *
349 * @param {Object} target The target to test
350 * @return {Boolean}
351 * @method
352 */
353 isArray: ('isArray' in Array) ? Array.isArray : function(value) {
354 return toString.call(value) === '[object Array]';
355 },
356
357 /**
358 * Returns true if the passed value is a JavaScript Date object, false otherwise.
359 * @param {Object} object The object to test
360 * @return {Boolean}
361 */
362 isDate: function(value) {
363 return toString.call(value) === '[object Date]';
364 },
365
366 /**
367 * Returns true if the passed value is a JavaScript Object, false otherwise.
368 * @param {Object} value The value to test
369 * @return {Boolean}
370 * @method
371 */
372 isObject: (toString.call(null) === '[object Object]') ?
373 function(value) {
374 // check ownerDocument here as well to exclude DOM nodes
375 return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
376 } :
377 function(value) {
378 return toString.call(value) === '[object Object]';
379 },
380
381 /**
382 * Returns true if the passed value is a JavaScript 'primitive', a string, number or boolean.
383 * @param {Object} value The value to test
384 * @return {Boolean}
385 */
386 isPrimitive: function(value) {
387 var type = typeof value;
388
389 return type === 'string' || type === 'number' || type === 'boolean';
390 },
391
392 /**
393 * Returns true if the passed value is a JavaScript Function, false otherwise.
394 * @param {Object} value The value to test
395 * @return {Boolean}
396 * @method
397 */
398 isFunction:
399 // Safari 3.x and 4.x returns 'function' for typeof <NodeList>, hence we need to fall back to using
400 // Object.prorotype.toString (slower)
401 (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
402 return toString.call(value) === '[object Function]';
403 } : function(value) {
404 return typeof value === 'function';
405 },
406
407 /**
408 * Returns true if the passed value is a number. Returns false for non-finite numbers.
409 * @param {Object} value The value to test
410 * @return {Boolean}
411 */
412 isNumber: function(value) {
413 return typeof value === 'number' && isFinite(value);
414 },
415
416 /**
417 * Validates that a value is numeric.
418 * @param {Object} value Examples: 1, '1', '2.34'
419 * @return {Boolean} True if numeric, false otherwise
420 */
421 isNumeric: function(value) {
422 return !isNaN(parseFloat(value)) && isFinite(value);
423 },
424
425 /**
426 * Returns true if the passed value is a string.
427 * @param {Object} value The value to test
428 * @return {Boolean}
429 */
430 isString: function(value) {
431 return typeof value === 'string';
432 },
433
434 /**
435 * Returns true if the passed value is a boolean.
436 *
437 * @param {Object} value The value to test
438 * @return {Boolean}
439 */
440 isBoolean: function(value) {
441 return typeof value === 'boolean';
442 },
443
444 /**
445 * Returns true if the passed value is an HTMLElement
446 * @param {Object} value The value to test
447 * @return {Boolean}
448 */
449 isElement: function(value) {
450 return value ? value.nodeType === 1 : false;
451 },
452
453 /**
454 * Returns true if the passed value is a TextNode
455 * @param {Object} value The value to test
456 * @return {Boolean}
457 */
458 isTextNode: function(value) {
459 return value ? value.nodeName === "#text" : false;
460 },
461
462 /**
463 * Returns true if the passed value is defined.
464 * @param {Object} value The value to test
465 * @return {Boolean}
466 */
467 isDefined: function(value) {
468 return typeof value !== 'undefined';
469 },
470
471 /**
472 * Returns true if the passed value is iterable, false otherwise
473 * @param {Object} value The value to test
474 * @return {Boolean}
475 */
476 isIterable: function(value) {
477 return (value && typeof value !== 'string') ? value.length !== undefined : false;
478 }
479 });
480
481 Ext.apply(Ext, {
482
483 /**
484 * Clone almost any type of variable including array, object, DOM nodes and Date without keeping the old reference
485 * @param {Object} item The variable to clone
486 * @return {Object} clone
487 */
488 clone: function(item) {
489 if (item === null || item === undefined) {
490 return item;
491 }
492
493 // DOM nodes
494 // TODO proxy this to Ext.Element.clone to handle automatic id attribute changing
495 // recursively
496 if (item.nodeType && item.cloneNode) {
497 return item.cloneNode(true);
498 }
499
500 var type = toString.call(item);
501
502 // Date
503 if (type === '[object Date]') {
504 return new Date(item.getTime());
505 }
506
507 var i, j, k, clone, key;
508
509 // Array
510 if (type === '[object Array]') {
511 i = item.length;
512
513 clone = [];
514
515 while (i--) {
516 clone[i] = Ext.clone(item[i]);
517 }
518 }
519 // Object
520 else if (type === '[object Object]' && item.constructor === Object) {
521 clone = {};
522
523 for (key in item) {
524 clone[key] = Ext.clone(item[key]);
525 }
526
527 if (enumerables) {
528 for (j = enumerables.length; j--;) {
529 k = enumerables[j];
530 clone[k] = item[k];
531 }
532 }
533 }
534
535 return clone || item;
536 },
537
538 /**
539 * @private
540 * Generate a unique reference of Ext in the global scope, useful for sandboxing
541 */
542 getUniqueGlobalNamespace: function() {
543 var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
544
545 if (uniqueGlobalNamespace === undefined) {
546 var i = 0;
547
548 do {
549 uniqueGlobalNamespace = 'ExtBox' + (++i);
550 } while (Ext.global[uniqueGlobalNamespace] !== undefined);
551
552 Ext.global[uniqueGlobalNamespace] = Ext;
553 this.uniqueGlobalNamespace = uniqueGlobalNamespace;
554 }
555
556 return uniqueGlobalNamespace;
557 },
558
559 /**
560 * @private
561 */
562 functionFactory: function() {
563 var args = Array.prototype.slice.call(arguments);
564
565 if (args.length > 0) {
566 args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
567 args[args.length - 1];
568 }
569
570 return Function.prototype.constructor.apply(Function.prototype, args);
571 }
572 });
573
574 /**
575 * Old alias to {@link Ext#typeOf}
576 * @deprecated 4.0.0 Use {@link Ext#typeOf} instead
577 * @method
578 * @alias Ext#typeOf
579 */
580 Ext.type = Ext.typeOf;
581
582})();
583
584/**
585 * @author Jacky Nguyen <jacky@sencha.com>
586 * @docauthor Jacky Nguyen <jacky@sencha.com>
587 * @class Ext.Version
588 *
589 * A utility class that wrap around a string version number and provide convenient
590 * method to perform comparison. See also: {@link Ext.Version#compare compare}. Example:
591
592 var version = new Ext.Version('1.0.2beta');
593 console.log("Version is " + version); // Version is 1.0.2beta
594
595 console.log(version.getMajor()); // 1
596 console.log(version.getMinor()); // 0
597 console.log(version.getPatch()); // 2
598 console.log(version.getBuild()); // 0
599 console.log(version.getRelease()); // beta
600
601 console.log(version.isGreaterThan('1.0.1')); // True
602 console.log(version.isGreaterThan('1.0.2alpha')); // True
603 console.log(version.isGreaterThan('1.0.2RC')); // False
604 console.log(version.isGreaterThan('1.0.2')); // False
605 console.log(version.isLessThan('1.0.2')); // True
606
607 console.log(version.match(1.0)); // True
608 console.log(version.match('1.0.2')); // True
609
610 * @markdown
611 */
612(function() {
613
614// Current core version
615var version = '4.0.7', Version;
616 Ext.Version = Version = Ext.extend(Object, {
617
618 /**
619 * @param {String/Number} version The version number in the follow standard format: major[.minor[.patch[.build[release]]]]
620 * Examples: 1.0 or 1.2.3beta or 1.2.3.4RC
621 * @return {Ext.Version} this
622 */
623 constructor: function(version) {
624 var parts, releaseStartIndex;
625
626 if (version instanceof Version) {
627 return version;
628 }
629
630 this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
631
632 releaseStartIndex = this.version.search(/([^\d\.])/);
633
634 if (releaseStartIndex !== -1) {
635 this.release = this.version.substr(releaseStartIndex, version.length);
636 this.shortVersion = this.version.substr(0, releaseStartIndex);
637 }
638
639 this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
640
641 parts = this.version.split('.');
642
643 this.major = parseInt(parts.shift() || 0, 10);
644 this.minor = parseInt(parts.shift() || 0, 10);
645 this.patch = parseInt(parts.shift() || 0, 10);
646 this.build = parseInt(parts.shift() || 0, 10);
647
648 return this;
649 },
650
651 /**
652 * Override the native toString method
653 * @private
654 * @return {String} version
655 */
656 toString: function() {
657 return this.version;
658 },
659
660 /**
661 * Override the native valueOf method
662 * @private
663 * @return {String} version
664 */
665 valueOf: function() {
666 return this.version;
667 },
668
669 /**
670 * Returns the major component value
671 * @return {Number} major
672 */
673 getMajor: function() {
674 return this.major || 0;
675 },
676
677 /**
678 * Returns the minor component value
679 * @return {Number} minor
680 */
681 getMinor: function() {
682 return this.minor || 0;
683 },
684
685 /**
686 * Returns the patch component value
687 * @return {Number} patch
688 */
689 getPatch: function() {
690 return this.patch || 0;
691 },
692
693 /**
694 * Returns the build component value
695 * @return {Number} build
696 */
697 getBuild: function() {
698 return this.build || 0;
699 },
700
701 /**
702 * Returns the release component value
703 * @return {Number} release
704 */
705 getRelease: function() {
706 return this.release || '';
707 },
708
709 /**
710 * Returns whether this version if greater than the supplied argument
711 * @param {String/Number} target The version to compare with
712 * @return {Boolean} True if this version if greater than the target, false otherwise
713 */
714 isGreaterThan: function(target) {
715 return Version.compare(this.version, target) === 1;
716 },
717
718 /**
719 * Returns whether this version if smaller than the supplied argument
720 * @param {String/Number} target The version to compare with
721 * @return {Boolean} True if this version if smaller than the target, false otherwise
722 */
723 isLessThan: function(target) {
724 return Version.compare(this.version, target) === -1;
725 },
726
727 /**
728 * Returns whether this version equals to the supplied argument
729 * @param {String/Number} target The version to compare with
730 * @return {Boolean} True if this version equals to the target, false otherwise
731 */
732 equals: function(target) {
733 return Version.compare(this.version, target) === 0;
734 },
735
736 /**
737 * Returns whether this version matches the supplied argument. Example:
738 * <pre><code>
739 * var version = new Ext.Version('1.0.2beta');
740 * console.log(version.match(1)); // True
741 * console.log(version.match(1.0)); // True
742 * console.log(version.match('1.0.2')); // True
743 * console.log(version.match('1.0.2RC')); // False
744 * </code></pre>
745 * @param {String/Number} target The version to compare with
746 * @return {Boolean} True if this version matches the target, false otherwise
747 */
748 match: function(target) {
749 target = String(target);
750 return this.version.substr(0, target.length) === target;
751 },
752
753 /**
754 * Returns this format: [major, minor, patch, build, release]. Useful for comparison
755 * @return {Number[]}
756 */
757 toArray: function() {
758 return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
759 },
760
761 /**
762 * Returns shortVersion version without dots and release
763 * @return {String}
764 */
765 getShortVersion: function() {
766 return this.shortVersion;
767 }
768 });
769
770 Ext.apply(Version, {
771 // @private
772 releaseValueMap: {
773 'dev': -6,
774 'alpha': -5,
775 'a': -5,
776 'beta': -4,
777 'b': -4,
778 'rc': -3,
779 '#': -2,
780 'p': -1,
781 'pl': -1
782 },
783
784 /**
785 * Converts a version component to a comparable value
786 *
787 * @static
788 * @param {Object} value The value to convert
789 * @return {Object}
790 */
791 getComponentValue: function(value) {
792 return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
793 },
794
795 /**
796 * Compare 2 specified versions, starting from left to right. If a part contains special version strings,
797 * they are handled in the following order:
798 * 'dev' < 'alpha' = 'a' < 'beta' = 'b' < 'RC' = 'rc' < '#' < 'pl' = 'p' < 'anything else'
799 *
800 * @static
801 * @param {String} current The current version to compare to
802 * @param {String} target The target version to compare to
803 * @return {Number} Returns -1 if the current version is smaller than the target version, 1 if greater, and 0 if they're equivalent
804 */
805 compare: function(current, target) {
806 var currentValue, targetValue, i;
807
808 current = new Version(current).toArray();
809 target = new Version(target).toArray();
810
811 for (i = 0; i < Math.max(current.length, target.length); i++) {
812 currentValue = this.getComponentValue(current[i]);
813 targetValue = this.getComponentValue(target[i]);
814
815 if (currentValue < targetValue) {
816 return -1;
817 } else if (currentValue > targetValue) {
818 return 1;
819 }
820 }
821
822 return 0;
823 }
824 });
825
826 Ext.apply(Ext, {
827 /**
828 * @private
829 */
830 versions: {},
831
832 /**
833 * @private
834 */
835 lastRegisteredVersion: null,
836
837 /**
838 * Set version number for the given package name.
839 *
840 * @param {String} packageName The package name, for example: 'core', 'touch', 'extjs'
841 * @param {String/Ext.Version} version The version, for example: '1.2.3alpha', '2.4.0-dev'
842 * @return {Ext}
843 */
844 setVersion: function(packageName, version) {
845 Ext.versions[packageName] = new Version(version);
846 Ext.lastRegisteredVersion = Ext.versions[packageName];
847
848 return this;
849 },
850
851 /**
852 * Get the version number of the supplied package name; will return the last registered version
853 * (last Ext.setVersion call) if there's no package name given.
854 *
855 * @param {String} packageName (Optional) The package name, for example: 'core', 'touch', 'extjs'
856 * @return {Ext.Version} The version
857 */
858 getVersion: function(packageName) {
859 if (packageName === undefined) {
860 return Ext.lastRegisteredVersion;
861 }
862
863 return Ext.versions[packageName];
864 },
865
866 /**
867 * Create a closure for deprecated code.
868 *
869 // This means Ext.oldMethod is only supported in 4.0.0beta and older.
870 // If Ext.getVersion('extjs') returns a version that is later than '4.0.0beta', for example '4.0.0RC',
871 // the closure will not be invoked
872 Ext.deprecate('extjs', '4.0.0beta', function() {
873 Ext.oldMethod = Ext.newMethod;
874
875 ...
876 });
877
878 * @param {String} packageName The package name
879 * @param {String} since The last version before it's deprecated
880 * @param {Function} closure The callback function to be executed with the specified version is less than the current version
881 * @param {Object} scope The execution scope (<tt>this</tt>) if the closure
882 * @markdown
883 */
884 deprecate: function(packageName, since, closure, scope) {
885 if (Version.compare(Ext.getVersion(packageName), since) < 1) {
886 closure.call(scope);
887 }
888 }
889 }); // End Versioning
890
891 Ext.setVersion('core', version);
892
893})();
894
895/**
896 * @class Ext.String
897 *
898 * A collection of useful static methods to deal with strings
899 * @singleton
900 */
901
902Ext.String = {
903 trimRegex: /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
904 escapeRe: /('|\\)/g,
905 formatRe: /\{(\d+)\}/g,
906 escapeRegexRe: /([-.*+?^${}()|[\]\/\\])/g,
907
908 /**
909 * Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
910 * @param {String} value The string to encode
911 * @return {String} The encoded text
912 * @method
913 */
914 htmlEncode: (function() {
915 var entities = {
916 '&': '&',
917 '>': '>',
918 '<': '<',
919 '"': '"'
920 }, keys = [], p, regex;
921
922 for (p in entities) {
923 keys.push(p);
924 }
925
926 regex = new RegExp('(' + keys.join('|') + ')', 'g');
927
928 return function(value) {
929 return (!value) ? value : String(value).replace(regex, function(match, capture) {
930 return entities[capture];
931 });
932 };
933 })(),
934
935 /**
936 * Convert certain characters (&, <, >, and ") from their HTML character equivalents.
937 * @param {String} value The string to decode
938 * @return {String} The decoded text
939 * @method
940 */
941 htmlDecode: (function() {
942 var entities = {
943 '&': '&',
944 '>': '>',
945 '<': '<',
946 '"': '"'
947 }, keys = [], p, regex;
948
949 for (p in entities) {
950 keys.push(p);
951 }
952
953 regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
954
955 return function(value) {
956 return (!value) ? value : String(value).replace(regex, function(match, capture) {
957 if (capture in entities) {
958 return entities[capture];
959 } else {
960 return String.fromCharCode(parseInt(capture.substr(2), 10));
961 }
962 });
963 };
964 })(),
965
966 /**
967 * Appends content to the query string of a URL, handling logic for whether to place
968 * a question mark or ampersand.
969 * @param {String} url The URL to append to.
970 * @param {String} string The content to append to the URL.
971 * @return (String) The resulting URL
972 */
973 urlAppend : function(url, string) {
974 if (!Ext.isEmpty(string)) {
975 return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
976 }
977
978 return url;
979 },
980
981 /**
982 * Trims whitespace from either end of a string, leaving spaces within the string intact. Example:
983 * @example
984var s = ' foo bar ';
985alert('-' + s + '-'); //alerts "- foo bar -"
986alert('-' + Ext.String.trim(s) + '-'); //alerts "-foo bar-"
987
988 * @param {String} string The string to escape
989 * @return {String} The trimmed string
990 */
991 trim: function(string) {
992 return string.replace(Ext.String.trimRegex, "");
993 },
994
995 /**
996 * Capitalize the given string
997 * @param {String} string
998 * @return {String}
999 */
1000 capitalize: function(string) {
1001 return string.charAt(0).toUpperCase() + string.substr(1);
1002 },
1003
1004 /**
1005 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
1006 * @param {String} value The string to truncate
1007 * @param {Number} length The maximum length to allow before truncating
1008 * @param {Boolean} word True to try to find a common word break
1009 * @return {String} The converted text
1010 */
1011 ellipsis: function(value, len, word) {
1012 if (value && value.length > len) {
1013 if (word) {
1014 var vs = value.substr(0, len - 2),
1015 index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
1016 if (index !== -1 && index >= (len - 15)) {
1017 return vs.substr(0, index) + "...";
1018 }
1019 }
1020 return value.substr(0, len - 3) + "...";
1021 }
1022 return value;
1023 },
1024
1025 /**
1026 * Escapes the passed string for use in a regular expression
1027 * @param {String} string
1028 * @return {String}
1029 */
1030 escapeRegex: function(string) {
1031 return string.replace(Ext.String.escapeRegexRe, "\\$1");
1032 },
1033
1034 /**
1035 * Escapes the passed string for ' and \
1036 * @param {String} string The string to escape
1037 * @return {String} The escaped string
1038 */
1039 escape: function(string) {
1040 return string.replace(Ext.String.escapeRe, "\\$1");
1041 },
1042
1043 /**
1044 * Utility function that allows you to easily switch a string between two alternating values. The passed value
1045 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
1046 * they are already different, the first value passed in is returned. Note that this method returns the new value
1047 * but does not change the current string.
1048 * <pre><code>
1049 // alternate sort directions
1050 sort = Ext.String.toggle(sort, 'ASC', 'DESC');
1051
1052 // instead of conditional logic:
1053 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
1054 </code></pre>
1055 * @param {String} string The current string
1056 * @param {String} value The value to compare to the current string
1057 * @param {String} other The new value to use if the string already equals the first value passed in
1058 * @return {String} The new value
1059 */
1060 toggle: function(string, value, other) {
1061 return string === value ? other : value;
1062 },
1063
1064 /**
1065 * Pads the left side of a string with a specified character. This is especially useful
1066 * for normalizing number and date strings. Example usage:
1067 *
1068 * <pre><code>
1069var s = Ext.String.leftPad('123', 5, '0');
1070// s now contains the string: '00123'
1071 </code></pre>
1072 * @param {String} string The original string
1073 * @param {Number} size The total length of the output string
1074 * @param {String} character (optional) The character with which to pad the original string (defaults to empty string " ")
1075 * @return {String} The padded string
1076 */
1077 leftPad: function(string, size, character) {
1078 var result = String(string);
1079 character = character || " ";
1080 while (result.length < size) {
1081 result = character + result;
1082 }
1083 return result;
1084 },
1085
1086 /**
1087 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
1088 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
1089 * <pre><code>
1090var cls = 'my-class', text = 'Some text';
1091var s = Ext.String.format('<div class="{0}">{1}</div>', cls, text);
1092// s now contains the string: '<div class="my-class">Some text</div>'
1093 </code></pre>
1094 * @param {String} string The tokenized string to be formatted
1095 * @param {String} value1 The value to replace token {0}
1096 * @param {String} value2 Etc...
1097 * @return {String} The formatted string
1098 */
1099 format: function(format) {
1100 var args = Ext.Array.toArray(arguments, 1);
1101 return format.replace(Ext.String.formatRe, function(m, i) {
1102 return args[i];
1103 });
1104 },
1105
1106 /**
1107 * Returns a string with a specified number of repititions a given string pattern.
1108 * The pattern be separated by a different string.
1109 *
1110 * var s = Ext.String.repeat('---', 4); // = '------------'
1111 * var t = Ext.String.repeat('--', 3, '/'); // = '--/--/--'
1112 *
1113 * @param {String} pattern The pattern to repeat.
1114 * @param {Number} count The number of times to repeat the pattern (may be 0).
1115 * @param {String} sep An option string to separate each pattern.
1116 */
1117 repeat: function(pattern, count, sep) {
1118 for (var buf = [], i = count; i--; ) {
1119 buf.push(pattern);
1120 }
1121 return buf.join(sep || '');
1122 }
1123};
1124
1125/**
1126 * @class Ext.Number
1127 *
1128 * A collection of useful static methods to deal with numbers
1129 * @singleton
1130 */
1131
1132(function() {
1133
1134var isToFixedBroken = (0.9).toFixed() !== '1';
1135
1136Ext.Number = {
1137 /**
1138 * Checks whether or not the passed number is within a desired range. If the number is already within the
1139 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
1140 * exceeded. Note that this method returns the constrained value but does not change the current number.
1141 * @param {Number} number The number to check
1142 * @param {Number} min The minimum number in the range
1143 * @param {Number} max The maximum number in the range
1144 * @return {Number} The constrained value if outside the range, otherwise the current value
1145 */
1146 constrain: function(number, min, max) {
1147 number = parseFloat(number);
1148
1149 if (!isNaN(min)) {
1150 number = Math.max(number, min);
1151 }
1152 if (!isNaN(max)) {
1153 number = Math.min(number, max);
1154 }
1155 return number;
1156 },
1157
1158 /**
1159 * Snaps the passed number between stopping points based upon a passed increment value.
1160 * @param {Number} value The unsnapped value.
1161 * @param {Number} increment The increment by which the value must move.
1162 * @param {Number} minValue The minimum value to which the returned value must be constrained. Overrides the increment..
1163 * @param {Number} maxValue The maximum value to which the returned value must be constrained. Overrides the increment..
1164 * @return {Number} The value of the nearest snap target.
1165 */
1166 snap : function(value, increment, minValue, maxValue) {
1167 var newValue = value,
1168 m;
1169
1170 if (!(increment && value)) {
1171 return value;
1172 }
1173 m = value % increment;
1174 if (m !== 0) {
1175 newValue -= m;
1176 if (m * 2 >= increment) {
1177 newValue += increment;
1178 } else if (m * 2 < -increment) {
1179 newValue -= increment;
1180 }
1181 }
1182 return Ext.Number.constrain(newValue, minValue, maxValue);
1183 },
1184
1185 /**
1186 * Formats a number using fixed-point notation
1187 * @param {Number} value The number to format
1188 * @param {Number} precision The number of digits to show after the decimal point
1189 */
1190 toFixed: function(value, precision) {
1191 if (isToFixedBroken) {
1192 precision = precision || 0;
1193 var pow = Math.pow(10, precision);
1194 return (Math.round(value * pow) / pow).toFixed(precision);
1195 }
1196
1197 return value.toFixed(precision);
1198 },
1199
1200 /**
1201 * Validate that a value is numeric and convert it to a number if necessary. Returns the specified default value if
1202 * it is not.
1203
1204Ext.Number.from('1.23', 1); // returns 1.23
1205Ext.Number.from('abc', 1); // returns 1
1206
1207 * @param {Object} value
1208 * @param {Number} defaultValue The value to return if the original value is non-numeric
1209 * @return {Number} value, if numeric, defaultValue otherwise
1210 */
1211 from: function(value, defaultValue) {
1212 if (isFinite(value)) {
1213 value = parseFloat(value);
1214 }
1215
1216 return !isNaN(value) ? value : defaultValue;
1217 }
1218};
1219
1220})();
1221
1222/**
1223 * @deprecated 4.0.0 Please use {@link Ext.Number#from} instead.
1224 * @member Ext
1225 * @method num
1226 * @alias Ext.Number#from
1227 */
1228Ext.num = function() {
1229 return Ext.Number.from.apply(this, arguments);
1230};
1231/**
1232 * @class Ext.Array
1233 * @singleton
1234 * @author Jacky Nguyen <jacky@sencha.com>
1235 * @docauthor Jacky Nguyen <jacky@sencha.com>
1236 *
1237 * A set of useful static methods to deal with arrays; provide missing methods for older browsers.
1238 */
1239(function() {
1240
1241 var arrayPrototype = Array.prototype,
1242 slice = arrayPrototype.slice,
1243 supportsSplice = function () {
1244 var array = [],
1245 lengthBefore,
1246 j = 20;
1247
1248 if (!array.splice) {
1249 return false;
1250 }
1251
1252 // This detects a bug in IE8 splice method:
1253 // see http://social.msdn.microsoft.com/Forums/en-US/iewebdevelopment/thread/6e946d03-e09f-4b22-a4dd-cd5e276bf05a/
1254
1255 while (j--) {
1256 array.push("A");
1257 }
1258
1259 array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");
1260
1261 lengthBefore = array.length; //41
1262 array.splice(13, 0, "XXX"); // add one element
1263
1264 if (lengthBefore+1 != array.length) {
1265 return false;
1266 }
1267 // end IE8 bug
1268
1269 return true;
1270 }(),
1271 supportsForEach = 'forEach' in arrayPrototype,
1272 supportsMap = 'map' in arrayPrototype,
1273 supportsIndexOf = 'indexOf' in arrayPrototype,
1274 supportsEvery = 'every' in arrayPrototype,
1275 supportsSome = 'some' in arrayPrototype,
1276 supportsFilter = 'filter' in arrayPrototype,
1277 supportsSort = function() {
1278 var a = [1,2,3,4,5].sort(function(){ return 0; });
1279 return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
1280 }(),
1281 supportsSliceOnNodeList = true,
1282 ExtArray;
1283
1284 try {
1285 // IE 6 - 8 will throw an error when using Array.prototype.slice on NodeList
1286 if (typeof document !== 'undefined') {
1287 slice.call(document.getElementsByTagName('body'));
1288 }
1289 } catch (e) {
1290 supportsSliceOnNodeList = false;
1291 }
1292
1293 function fixArrayIndex (array, index) {
1294 return (index < 0) ? Math.max(0, array.length + index)
1295 : Math.min(array.length, index);
1296 }
1297
1298 /*
1299 Does the same work as splice, but with a slightly more convenient signature. The splice
1300 method has bugs in IE8, so this is the implementation we use on that platform.
1301
1302 The rippling of items in the array can be tricky. Consider two use cases:
1303
1304 index=2
1305 removeCount=2
1306 /=====\
1307 +---+---+---+---+---+---+---+---+
1308 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1309 +---+---+---+---+---+---+---+---+
1310 / \/ \/ \/ \
1311 / /\ /\ /\ \
1312 / / \/ \/ \ +--------------------------+
1313 / / /\ /\ +--------------------------+ \
1314 / / / \/ +--------------------------+ \ \
1315 / / / /+--------------------------+ \ \ \
1316 / / / / \ \ \ \
1317 v v v v v v v v
1318 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
1319 | 0 | 1 | 4 | 5 | 6 | 7 | | 0 | 1 | a | b | c | 4 | 5 | 6 | 7 |
1320 +---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+---+
1321 A B \=========/
1322 insert=[a,b,c]
1323
1324 In case A, it is obvious that copying of [4,5,6,7] must be left-to-right so
1325 that we don't end up with [0,1,6,7,6,7]. In case B, we have the opposite; we
1326 must go right-to-left or else we would end up with [0,1,a,b,c,4,4,4,4].
1327 */
1328 function replaceSim (array, index, removeCount, insert) {
1329 var add = insert ? insert.length : 0,
1330 length = array.length,
1331 pos = fixArrayIndex(array, index);
1332
1333 // we try to use Array.push when we can for efficiency...
1334 if (pos === length) {
1335 if (add) {
1336 array.push.apply(array, insert);
1337 }
1338 } else {
1339 var remove = Math.min(removeCount, length - pos),
1340 tailOldPos = pos + remove,
1341 tailNewPos = tailOldPos + add - remove,
1342 tailCount = length - tailOldPos,
1343 lengthAfterRemove = length - remove,
1344 i;
1345
1346 if (tailNewPos < tailOldPos) { // case A
1347 for (i = 0; i < tailCount; ++i) {
1348 array[tailNewPos+i] = array[tailOldPos+i];
1349 }
1350 } else if (tailNewPos > tailOldPos) { // case B
1351 for (i = tailCount; i--; ) {
1352 array[tailNewPos+i] = array[tailOldPos+i];
1353 }
1354 } // else, add == remove (nothing to do)
1355
1356 if (add && pos === lengthAfterRemove) {
1357 array.length = lengthAfterRemove; // truncate array
1358 array.push.apply(array, insert);
1359 } else {
1360 array.length = lengthAfterRemove + add; // reserves space
1361 for (i = 0; i < add; ++i) {
1362 array[pos+i] = insert[i];
1363 }
1364 }
1365 }
1366
1367 return array;
1368 }
1369
1370 function replaceNative (array, index, removeCount, insert) {
1371 if (insert && insert.length) {
1372 if (index < array.length) {
1373 array.splice.apply(array, [index, removeCount].concat(insert));
1374 } else {
1375 array.push.apply(array, insert);
1376 }
1377 } else {
1378 array.splice(index, removeCount);
1379 }
1380 return array;
1381 }
1382
1383 function eraseSim (array, index, removeCount) {
1384 return replaceSim(array, index, removeCount);
1385 }
1386
1387 function eraseNative (array, index, removeCount) {
1388 array.splice(index, removeCount);
1389 return array;
1390 }
1391
1392 function spliceSim (array, index, removeCount) {
1393 var pos = fixArrayIndex(array, index),
1394 removed = array.slice(index, fixArrayIndex(array, pos+removeCount));
1395
1396 if (arguments.length < 4) {
1397 replaceSim(array, pos, removeCount);
1398 } else {
1399 replaceSim(array, pos, removeCount, slice.call(arguments, 3));
1400 }
1401
1402 return removed;
1403 }
1404
1405 function spliceNative (array) {
1406 return array.splice.apply(array, slice.call(arguments, 1));
1407 }
1408
1409 var erase = supportsSplice ? eraseNative : eraseSim,
1410 replace = supportsSplice ? replaceNative : replaceSim,
1411 splice = supportsSplice ? spliceNative : spliceSim;
1412
1413 // NOTE: from here on, use erase, replace or splice (not native methods)...
1414
1415 ExtArray = Ext.Array = {
1416 /**
1417 * Iterates an array or an iterable value and invoke the given callback function for each item.
1418 *
1419 * var countries = ['Vietnam', 'Singapore', 'United States', 'Russia'];
1420 *
1421 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
1422 * console.log(name);
1423 * });
1424 *
1425 * var sum = function() {
1426 * var sum = 0;
1427 *
1428 * Ext.Array.each(arguments, function(value) {
1429 * sum += value;
1430 * });
1431 *
1432 * return sum;
1433 * };
1434 *
1435 * sum(1, 2, 3); // returns 6
1436 *
1437 * The iteration can be stopped by returning false in the function callback.
1438 *
1439 * Ext.Array.each(countries, function(name, index, countriesItSelf) {
1440 * if (name === 'Singapore') {
1441 * return false; // break here
1442 * }
1443 * });
1444 *
1445 * {@link Ext#each Ext.each} is alias for {@link Ext.Array#each Ext.Array.each}
1446 *
1447 * @param {Array/NodeList/Object} iterable The value to be iterated. If this
1448 * argument is not iterable, the callback function is called once.
1449 * @param {Function} fn The callback function. If it returns false, the iteration stops and this method returns
1450 * the current `index`.
1451 * @param {Object} fn.item The item at the current `index` in the passed `array`
1452 * @param {Number} fn.index The current `index` within the `array`
1453 * @param {Array} fn.allItems The `array` it…
Large files files are truncated, but you can click here to view the full file