Source: UnitzParsed.js


/**
 * Instantiates a new parsed instance with a number, unit, string representation,
 * and optionally the unit class if the unit was recognized by Unitz.
 *
 * @memberof Unitz
 * @alias Parsed
 * @class
 * @constructor
 * @param {Number} value -
 *    The parsed number.
 * @param {String} unit -
 *    The unit for the number (empty string if no unit specified).
 * @param {Unitz.Class} [unitClass] -
 *    The class for the unit (if any).
 * @param {String} normal -
 *    The normalized representation of the number and unit combined. If a unit
 *    class is given this will be re-calculated using the proper singular/plural
 *    unit for it's group.
 */
function UnitzParsed(value, unit, unitClass, normal)
{
  /**
   * The current parsed value.
   *
   * @member {Number}
   */
  this.value = value;

  /**
   * The unit for the current value (if any).
   *
   * @member {String}
   */
  this.unit = unit;

  /**
   * The class of the unit (if any).
   *
   * @member {Unitz.Class}
   */
  this.unitClass = unitClass;

  /**
   * The group of the unit (if any).
   *
   * @member {Unitz.Group}
   */
  this.group = unitClass ? unitClass.groupMap[ unit ] : null;

  /**
   * The string representation of the parsed value. If this instance has a group
   * this will be the current value with the appropriate singular/plural unit -
   * otherwise this will be the input passed to the {@link Unitz.parse} function.
   *
   * @member {String}
   */
  this.normal = this.group ? this.group.addUnit( value ) : normal;
}

UnitzParsed.prototype =
{

  /**
   * Converts the current value to another unit. The default behavior is to
   * return a number in the desired unit - however you can specify a truthy value
   * for `returnFraction` and a {@Unitz.Fraction} will be returned. If the unit
   * to convert to is not a valid unit for this Parsed value - false will be
   * returned.
   *
   * ```javascript
   * var p = Unitz.parse('2 cups');
   * p.convert('qt');                 // 0.5
   * p.convert('qt', true);           // '1/2'
   * p.convert('qt', false, true);    // '0.5 qt'
   * p.convert('qt', true, true);     // '1/2 qt'
   *
   * var q = Unitz.parse('0.125 trees'); // unknown unit
   * q.convert('trees', true, true, 10, [2, 4, 8, 16]); // '1/8 trees'
   * ```
   *
   * @method
   * @memberof Unitz.Parsed#
   * @param {String} to -
   *    The unit to convert the current value to.
   * @param {Boolean} [returnFraction=false] -
   *    Whether the resulting conversion should return a {@link Unitz.Fraction}.
   * @param {Boolean} [withUnit=false] -
   *    Whether the value returned has the given unit appended to the end of it.
   *    If the returned value is a fraction the given unit will be appended to
   *    the {@link Unitz.Parsed#string} property.
   * @param {Number} [largestDenominator] -
   *    See {@link Unitz.Fraction}.
   * @param {Number[]} [classlessDenominators] -
   *    If the current value does not have a {@link Unitz.Group} (which stores
   *    the valid fraction denominators for the unit) you can specify which
   *    denominators to use when calculating the nearest fraction to the
   *    converted value.
   * @param {Boolean} [roundDown=false] -
   *    A fraction will try to find the closest value to `value` - sometimes the
   *    closest fraction is larger than the given `value` and it is used. You can
   *    pass true to this constructor and it will make sure the fraction determined
   *    is never over the given `value`.
   * @see Unitz.Fraction
   * @return {Number|String|Unitz.Fraction|false}
   */
  convert: function(to, returnFraction, withUnit, largestDenominator, classlessDenominators, roundDown)
  {
    var converted = convert( this, to );

    if ( converted !== false && returnFraction )
    {
      var denominators = this.group ? this.group.denominators : classlessDenominators;

      if ( isArray( denominators ) )
      {
        converted = new UnitzFraction( converted, denominators, largestDenominator, roundDown );

        if ( isObject( converted ) && withUnit && to )
        {
          converted.string = createNormal( converted.string, to );
        }
      }
    }

    if ( withUnit && isNumber( converted ) && to )
    {
      converted = createNormal( converted, to );
    }

    return converted;
  },

  /**
   * Determines the best way to represent the current value. {@link Unitz.best}
   *
   * @param {Boolean} [returnFraction=false] -
   *    Whether the {@link Unitz.Parsed#normal} returned should be converted to
   *    a fraction (if a nice fraction exists).
   * @param {Boolean} [abbreviations=false] -
   *    If the returned value should use abbreviations if they're available.
   * @param {Number} [largestDenominator] -
   *    See {@link Unitz.Fraction}.
   * @see Unitz.best
   * @return {Unitz.Parsed}
   */
  best: function(returnFraction, abbreviations, largestDenominator)
  {
    return best( this, returnFraction, abbreviations, largestDenominator );
  },

  /**
   * Returns the fraction representation of this parsed value.
   *
   * @param {Boolean} [withUnit=false] -
   *    If the {@link Unitz.Fraction#string} property should have the unit added
   *    to it.
   * @param {Number[]} [denominators] -
   *    The array of denominators to use when converting the given value into a
   *    fraction. If a falsy value is given the denonimators of this parsed group
   *    will be used if a unit group has been determined.
   * @param {Number} [largestDenominator] -
   *    Sometimes you don't want to use all of the denominators in the above array
   *    (it could be from a {@link Unitz.Group}) and you would like to set a max.
   *    If the denominators given has something like `[2, 4, 8, 100]` and you
   *    don't want a fraction like `3/100` you can set the `largestDenominator` to
   *    a number lower than 100 and you won't ever get that denominator.
   * @param {Boolean} [roundDown=false] -
   *    A fraction will try to find the closest value to `value` - sometimes the
   *    closest fraction is larger than the given `value` and it is used. You can
   *    pass true to this constructor and it will make sure the fraction determined
   *    is never over the given `value`.
   * @return {Unitz.Fraction} -
   *    A new instance of Unitz.Fraction which is a representation of the parsed
   *    value.
   */
  fraction: function(withUnit, denominators, largestDenominator, roundDown)
  {
    var groupDenominators = this.group ? this.group.denominators : [];
    var fractionDenominators = denominators || groupDenominators;
    var fraction = new UnitzFraction( this.value, fractionDenominators, largestDenominator, roundDown );

    if (withUnit)
    {
      fraction.string = createNormal( fraction.string, this.unit );
    }

    return fraction;
  }

};

/**
 * Returns a unitless {@link Unitz.Parsed} instance for the given number.
 *
 * @method fromNumber
 * @memberof Unitz.Parsed
 * @param {Number} number -
 *    The value of the parsed instance returned.
 * @return {Unitz.Parsed}
 */
UnitzParsed.fromNumber = function(number)
{
  return new UnitzParsed(number, '', null, number, null);
};