PageRenderTime 98ms CodeModel.GetById 10ms app.highlight 67ms RepoModel.GetById 0ms app.codeStats 2ms

/ext-4.0.7/builds/ext-foundation-dev.js

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

Large files files are truncated, but you can click here to view the full file