/** * @module Core * @namespace springroll */ (function() { var Debug; /** * An enumeration value. This class is private, and is only used by Enum. * @class EnumValue * @private * @constructor * @param {String} name The name of the enum value. * @param {int} value The integer value of the enum. * @param {String} toString A string for toString() to return, instead of the name. */ var EnumValue = function(name, value, toString) { if (Debug === undefined) Debug = include('springroll.Debug', false); /** * The name of the value, for reflection or logging purposes. * @property {String} name */ this.name = name; /** * The integer value of this enum entry. * @property {int} _value * @private */ this._value = value; /** * A string for toString() to return, instead of the name. * @property {String} _toString * @private */ this._toString = toString || this.name; }; /** * The integer value of this enum entry. * @property {int} asInt */ Object.defineProperty(EnumValue.prototype, "asInt", { get: function() { return this._value; } }); EnumValue.prototype.toString = function() { return this._toString; }; /** * An enumeration, similar to Enums in C#. Each value is created as an EnumValue on the Enum, * referenced as a property with the same name as the EnumValue. Examples: * var myEnum = new springroll.Enum( "valueOf0", "valueOf1", "valueOf2"); var myOtherEnum = new springroll.Enum( {name: "one", value:"1", toString:"I am the One!"}, "two", {name:"screwSequentialNumbers", value:42}); myEnum.valueOf0 != 0;//enum values are not integers myEnum.valueOf1 != myOtherEnum.one;//enum values are not the same as other enums myEnum.valueOf2.asInt == 2;//enum values can be explicitly compared to integers myOtherEnum.screwSequentialNumbers == myOtherEnum.valueFromInt(42);//can use ints to get values console.log(myOtherEnum.one.toString());//outputs "I am the One!" for (var i in myEnum) console.log(i); //outputs "valueOf0","valueOf1","valueOf2" * * @class Enum * @constructor * @param {Array|String|Object} arguments * The list of enumeration values. You can pass either an * array or a list of parameters. Each string will be * the previous value plus one, while objects with * 'name' and 'value' properties will have the specified * numeric value. */ var Enum = function() { var args = Array.isArray(arguments[0]) ? arguments[0] : Array.prototype.slice.call(arguments); /** * A potentially sparse array of each enum value, stored by integer values. * @property {Array} _byValue * @private */ Object.defineProperty(this, '_byValue', { enumerable: false, writable: false, value: [] }); /** * The values that this Enum was initialized with. We save this so * that we can potentially pass this via Bellhop and re-initialize. * @public * @property {Array} rawEnumValues */ Object.defineProperty(this, 'rawEnumValues', { enumerable: false, writable: false, value: args }); var counter = 0; var item; var value; var name; // Create an EnumValue for each argument provided for (var i = 0, len = args.length; i < len; ++i) { if (typeof args[i] == "string") { name = args[i]; } else { name = args[i].name; value = args[i].value || counter; counter = value; } // if name already exists in Enum if (this[name]) { if (DEBUG && Debug) { Debug.error("Error creating enum value " + name + ": " + value + " - an enum value already exists with that name."); } continue; } item = (typeof args[i] == "string") ? new EnumValue(name, counter, name) : new EnumValue(name, value, args[i].toString || name); this[item.name] = item; if (this._byValue[counter]) { if (Array.isArray(this._byValue[counter])) { this._byValue[counter].push(item); } else { this._byValue[counter] = [this._byValue[counter], item]; } } else { this._byValue[counter] = item; } counter++; } /** * The count of values the enum was initialized with. * @public * @property {int} length */ Object.defineProperty(this, 'length', { enumerable: false, writable: false, value: args.length }); /** * Retrieves the next EnumValue in the Enum (loops to first value at end). * @method {EnumValue} next * @param {EnumValue} input An EnumValue to retrieve the value that follows. * @return {EnumValue} */ Object.defineProperty(this, 'next', { enumerable: false, writable: false, // {EnumValue} input value: function(input) { var nextInt = input.asInt + 1; if (nextInt >= counter) { return this.first; } return this.valueFromInt(nextInt); } }); /** * Retrieves the first EnumValue in the Enum * @method {EnumValue} first * @return {EnumValue} */ Object.defineProperty(this, 'first', { enumerable: false, writable: false, value: this.valueFromInt(args[0].value || 0) }); /** * Retrieves the last EnumValue in the Enum * @method {EnumValue} last * @return {EnumValue} */ Object.defineProperty(this, 'last', { enumerable: false, writable: false, value: this.valueFromInt(counter - 1) }); }; var p = extend(Enum); /** * Gets an enum value by integer value. If you have multiple enum values with the same integer * value, this will always retrieve the first enum value. * @method {Array} valueFromInt * @param {int} input The integer value to get an enum value for. * @return {EnumValue} The EnumValue that represents the input integer. */ Object.defineProperty(p, 'valueFromInt', { enumerable: false, writable: false, value: function(input) { var rtn = this._byValue[input]; if (rtn) { return Array.isArray(rtn) ? rtn[0] : rtn; } return null; } }); namespace('springroll').Enum = Enum; }());