//@tag foundation,core //@define Ext.Version //@require Ext /** * @author Jacky Nguyen <jacky@sencha.com> * @docauthor Jacky Nguyen <jacky@sencha.com> * @class Ext.Version * * A utility class that wrap around a string version number and provide convenient * method to perform comparison. See also: {@link Ext.Version#compare compare}. Example: * * var version = new Ext.Version('1.0.2beta'); * console.log("Version is " + version); // Version is 1.0.2beta * * console.log(version.getMajor()); // 1 * console.log(version.getMinor()); // 0 * console.log(version.getPatch()); // 2 * console.log(version.getBuild()); // 0 * console.log(version.getRelease()); // beta * * console.log(version.isGreaterThan('1.0.1')); // true * console.log(version.isGreaterThan('1.0.2alpha')); // true * console.log(version.isGreaterThan('1.0.2RC')); // false * console.log(version.isGreaterThan('1.0.2')); // false * console.log(version.isLessThan('1.0.2')); // true * * console.log(version.match(1.0)); // true * console.log(version.match('1.0.2')); // true */ (function() { // Current core version var version = '4.1.0', Version; Ext.Version = Version = Ext.extend(Object, { /** * Creates new Version object. * @param {String/Number} version The version number in the follow standard format: major[.minor[.patch[.build[release]]]] * Examples: 1.0 or 1.2.3beta or 1.2.3.4RC * @return {Ext.Version} this */ constructor: function(version) { var toNumber = this.toNumber, parts, releaseStartIndex; if (version instanceof Version) { return version; } this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, ''); releaseStartIndex = this.version.search(/([^\d\.])/); if (releaseStartIndex !== -1) { this.release = this.version.substr(releaseStartIndex, version.length); this.shortVersion = this.version.substr(0, releaseStartIndex); } this.shortVersion = this.shortVersion.replace(/[^\d]/g, ''); parts = this.version.split('.'); this.major = toNumber(parts.shift()); this.minor = toNumber(parts.shift()); this.patch = toNumber(parts.shift()); this.build = toNumber(parts.shift()); return this; }, /** * @param {Number} value * @return {Number} */ toNumber: function(value) { value = parseInt(value || 0, 10); if (isNaN(value)) { value = 0; } return value; }, /** * Override the native `toString()` method. * @private * @return {String} version */ toString: function() { return this.version; }, /** * Override the native `valueOf()` method. * @private * @return {String} version */ valueOf: function() { return this.version; }, /** * Returns the major component value. * @return {Number} major */ getMajor: function() { return this.major || 0; }, /** * Returns the minor component value. * @return {Number} minor */ getMinor: function() { return this.minor || 0; }, /** * Returns the patch component value. * @return {Number} patch */ getPatch: function() { return this.patch || 0; }, /** * Returns the build component value. * @return {Number} build */ getBuild: function() { return this.build || 0; }, /** * Returns the release component value. * @return {Number} release */ getRelease: function() { return this.release || ''; }, /** * Returns whether this version if greater than the supplied argument. * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version if greater than the target, `false` otherwise. */ isGreaterThan: function(target) { return Version.compare(this.version, target) === 1; }, /** * Returns whether this version if greater than or equal to the supplied argument. * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version if greater than or equal to the target, `false` otherwise. */ isGreaterThanOrEqual: function(target) { return Version.compare(this.version, target) >= 0; }, /** * Returns whether this version if smaller than the supplied argument. * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version if smaller than the target, `false` otherwise. */ isLessThan: function(target) { return Version.compare(this.version, target) === -1; }, /** * Returns whether this version if less than or equal to the supplied argument. * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version if less than or equal to the target, `false` otherwise. */ isLessThanOrEqual: function(target) { return Version.compare(this.version, target) <= 0; }, /** * Returns whether this version equals to the supplied argument. * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version equals to the target, `false` otherwise. */ equals: function(target) { return Version.compare(this.version, target) === 0; }, /** * Returns whether this version matches the supplied argument. Example: * * var version = new Ext.Version('1.0.2beta'); * console.log(version.match(1)); // true * console.log(version.match(1.0)); // true * console.log(version.match('1.0.2')); // true * console.log(version.match('1.0.2RC')); // false * * @param {String/Number} target The version to compare with. * @return {Boolean} `true` if this version matches the target, `false` otherwise. */ match: function(target) { target = String(target); return this.version.substr(0, target.length) === target; }, /** * Returns this format: [major, minor, patch, build, release]. Useful for comparison. * @return {Number[]} */ toArray: function() { return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()]; }, /** * Returns shortVersion version without dots and release. * @return {String} */ getShortVersion: function() { return this.shortVersion; }, /** * Convenient alias to {@link Ext.Version#isGreaterThan isGreaterThan} * @param {String/Number} target * @return {Boolean} */ gt: function() { return this.isGreaterThan.apply(this, arguments); }, /** * Convenient alias to {@link Ext.Version#isLessThan isLessThan} * @param {String/Number} target * @return {Boolean} */ lt: function() { return this.isLessThan.apply(this, arguments); }, /** * Convenient alias to {@link Ext.Version#isGreaterThanOrEqual isGreaterThanOrEqual} * @param {String/Number} target * @return {Boolean} */ gtEq: function() { return this.isGreaterThanOrEqual.apply(this, arguments); }, /** * Convenient alias to {@link Ext.Version#isLessThanOrEqual isLessThanOrEqual} * @param {String/Number} target * @return {Boolean} */ ltEq: function() { return this.isLessThanOrEqual.apply(this, arguments); } }); Ext.apply(Version, { // @private releaseValueMap: { 'dev': -6, 'alpha': -5, 'a': -5, 'beta': -4, 'b': -4, 'rc': -3, '#': -2, 'p': -1, 'pl': -1 }, /** * Converts a version component to a comparable value. * * @static * @param {Object} value The value to convert * @return {Object} */ getComponentValue: function(value) { return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10)); }, /** * Compare 2 specified versions, starting from left to right. If a part contains special version strings, * they are handled in the following order: * 'dev' < 'alpha' = 'a' < 'beta' = 'b' < 'RC' = 'rc' < '#' < 'pl' = 'p' < 'anything else' * * @static * @param {String} current The current version to compare to. * @param {String} target The target version to compare to. * @return {Number} Returns -1 if the current version is smaller than the target version, 1 if greater, and 0 if they're equivalent. */ compare: function(current, target) { var currentValue, targetValue, i; current = new Version(current).toArray(); target = new Version(target).toArray(); for (i = 0; i < Math.max(current.length, target.length); i++) { currentValue = this.getComponentValue(current[i]); targetValue = this.getComponentValue(target[i]); if (currentValue < targetValue) { return -1; } else if (currentValue > targetValue) { return 1; } } return 0; } }); Ext.apply(Ext, { /** * @private */ versions: {}, /** * @private */ lastRegisteredVersion: null, /** * Set version number for the given package name. * * @param {String} packageName The package name, for example: 'core', 'touch', 'extjs'. * @param {String/Ext.Version} version The version, for example: '1.2.3alpha', '2.4.0-dev'. * @return {Ext} */ setVersion: function(packageName, version) { Ext.versions[packageName] = new Version(version); Ext.lastRegisteredVersion = Ext.versions[packageName]; return this; }, /** * Get the version number of the supplied package name; will return the last registered version * (last `Ext.setVersion()` call) if there's no package name given. * * @param {String} packageName (Optional) The package name, for example: 'core', 'touch', 'extjs'. * @return {Ext.Version} The version. */ getVersion: function(packageName) { if (packageName === undefined) { return Ext.lastRegisteredVersion; } return Ext.versions[packageName]; }, /** * Create a closure for deprecated code. * * // This means Ext.oldMethod is only supported in 4.0.0beta and older. * // If Ext.getVersion('extjs') returns a version that is later than '4.0.0beta', for example '4.0.0RC', * // the closure will not be invoked * Ext.deprecate('extjs', '4.0.0beta', function() { * Ext.oldMethod = Ext.newMethod; * // ... * }); * * @param {String} packageName The package name. * @param {String} since The last version before it's deprecated. * @param {Function} closure The callback function to be executed with the specified version is less than the current version. * @param {Object} scope The execution scope (`this`) if the closure */ deprecate: function(packageName, since, closure, scope) { if (Version.compare(Ext.getVersion(packageName), since) < 1) { closure.call(scope); } } }); // End Versioning Ext.setVersion('core', version); })();