PageRenderTime 87ms CodeModel.GetById 31ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 2ms

/ext-4.0.7/ext-all-debug-w-comments.js

https://bitbucket.org/srogerf/javascript
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            '&': '&amp;',
 917            '>': '&gt;',
 918            '<': '&lt;',
 919            '"': '&quot;'
 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            '&amp;': '&',
 944            '&gt;': '>',
 945            '&lt;': '<',
 946            '&quot;': '"'
 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('&lt;div class="{0}">{1}&lt;/div>', cls, text);
1092// s now contains the string: '&lt;div class="my-class">Some text&lt;/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