| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 | 'use strict';/** * Licensed Materials - Property of IBM * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2016, 2017 * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */define(['../../lib/@waca/core-client/js/core-client/ui/core/Class'], function (Class) {	var ScaleUtil = {};	/**  * Functions used to handle calculation of scale options for infographic display functionality  *  */	ScaleUtil = Class.extend({		// Constants that handles conversion between numeric and text values. Used for readability, as numbers are used for scale slider min/max but they interpret as text values		SCALE_VALUE_FEW: 0,		SCALE_VALUE_DEFAULT: 1,		SCALE_VALUE_MANY: 2,		PERCENT_OPTIMAL_VALUE: 0.1,		PERCENT_SCALE_OPTIONS: [0.01, 0.1, 1],		/**   * Calculates the default scale value for a given input number   * @param rawNum - Input number to be infographically displayed   * @param isPercent - If the raw number is used to represent a percentage infographic   * @returns The default scale value to be used   */		calcOptimalValue: function calcOptimalValue(rawNum, isPercent) {			// If rawNum is null (i.e. no value provided, treat same as zero case to avoid returning errors later on			if (rawNum === null) {				rawNum = 0;			}			// Null if not a number			if (typeof rawNum !== 'number') {				return null;			}			if (isPercent) {				return this.PERCENT_OPTIMAL_VALUE;			}			// Take abs to handle negative numbers			var absNum = Math.abs(rawNum);			var sign = this.getSign(rawNum) || 1;			var numLen = Math.ceil(Math.log(absNum + 1) / Math.LN10);			// Default optimal value is 1.			var optimalValue = 1;			// If the number of digits is greater than 2 than calculate the optimal value			if (numLen > 2) {				optimalValue = Math.pow(10, numLen - 2);			}			return optimalValue * sign;		},		/**   * Gets an object containing a list of scale options as well as the default for a given number   * @param rawNum - Input number to be infographically displayed   * @param isPercent - If the raw number is used to represent a percentage infographic   * @returns An object containing an array of scaling options to be used, as well as the default scale to be shown   */		getScalingProperties: function getScalingProperties(rawNum, isPercent) {			// If rawNum is null (i.e. no value provided, treat same as zero case to avoid returning errors later on			if (rawNum === null) {				rawNum = 0;			}			// Null if not a number			if (typeof rawNum !== 'number') {				return null;			}			if (isPercent) {				return {					availableScales: this.PERCENT_SCALE_OPTIONS,					optimalScale: this.PERCENT_OPTIMAL_VALUE,					scalingOptions: [this.SCALE_VALUE_FEW, this.SCALE_VALUE_DEFAULT, this.SCALE_VALUE_MANY]				};			}			// get the absolute number			var absNum = Math.abs(rawNum);			// get the sign of the number to help handle negative numbers			var sign = this.getSign(rawNum) || 1;			// Get the ideal scale for the given number			var optimalValue = this.calcOptimalValue(absNum);			var availableScales = [optimalValue * sign];			// Only add lower scale option if the default is greater than one			if (optimalValue > 1) {				availableScales.unshift(optimalValue / 10 * sign);			}			// Check if potential high value is valid scale option for input number			var potentialHigh = optimalValue * 10;			if (absNum / potentialHigh >= 1) {				availableScales.push(potentialHigh * sign);			}			// Assemble both parts of final product to be returned to user			var result = {				availableScales: availableScales,				optimalScale: optimalValue * sign			};			result.scalingOptions = this._getScaleOptions(result, isPercent);			return result;		},		/**   * Returns the corresponding min/max values for slider which user utilizes to select preferred scale option   * @param {Number} rawNum - Raw input number which is being used to determine the scale   * @param isPercent - If the raw number is used to represent a percentage infographic   * @returns result object containing min and max value for slider   */		getMinMax: function getMinMax(rawNum, isPercent) {			// If rawNum is null (i.e. no value provided, treat same as zero case to avoid returning errors later on			if (rawNum === null) {				rawNum = 0;			}			var scales = this.getScalingProperties(rawNum, isPercent);			return {				min: scales.scalingOptions[0],				max: scales.scalingOptions[scales.scalingOptions.length - 1]			};		},		/**   * Given a corresponding value and scale to use, calculate the number of shapes and partial shapes to return to the user   * @param value - The value we are calculating the number off of   * @param scale - The scale that will be used   * @param isPercent - If the raw number is used to represent a percentage infographic   * @returns An object that contains the number of shapes and partial shapes to be displayed in the infographic summary   */		getScaleComponents: function getScaleComponents(value, scale, isPercent) {			// If rawNum is null (i.e. no value provided, treat same as zero case to avoid returning errors later on			if (value === null) {				value = 0;			}			/**    * Used to divide a number by a floating point decimal, which can sometimes lead to repeating decimal values using the normal '/' operator    * @param numerator - Numerator of division expression    * @param denominator - Denominator of division expression    * @returns Result of numerator divided by denominator    */			function _division(numerator, denominator) {				while (denominator < 1 && denominator > 0) {					denominator *= 10;					numerator *= 10;				}				return numerator / denominator;			}			/**    * Used to find the remainder of a number by a floating point decimal, which can sometimes lead to repeating decimal values using the normal '%' operator    * @param numerator - Numerator of remainder expression    * @param denominator - Denominator of remainder expression    * @returns remainder of expression    */			function _remainder(numerator, denominator) {				return numerator - denominator * Math.floor(_division(numerator, denominator));			}			value = Math.abs(value);			scale = Math.abs(scale);			var numShapes = Math.floor(_division(value, scale));			var partialValue = _division(_remainder(value, scale), scale);			partialValue = parseFloat(partialValue.toFixed(2));			var numGreyedShapes;			if (isPercent) {				numGreyedShapes = _division(1, scale) - numShapes - Math.ceil(partialValue);			} else {				numGreyedShapes = 0;			}			return {				numShapes: numShapes,				partialValue: partialValue,				numGreyedShapes: numGreyedShapes			};		},		_getScaleOptions: function _getScaleOptions(scaleData) {			var numOfScales = scaleData.availableScales.length;			var result;			if (numOfScales === 3) {				result = [this.SCALE_VALUE_FEW, this.SCALE_VALUE_DEFAULT, this.SCALE_VALUE_MANY];			} else if (numOfScales === 1) {				result = [this.SCALE_VALUE_DEFAULT];			} else if (scaleData.availableScales.indexOf(scaleData.optimalScale) === 0) {				result = [this.SCALE_VALUE_FEW, this.SCALE_VALUE_DEFAULT];			} else if (scaleData.availableScales.indexOf(scaleData.optimalScale) === 1) {				result = [this.SCALE_VALUE_DEFAULT, this.SCALE_VALUE_MANY];			}			return result;		},		getSign: function getSign(x) {			x = +x; // convert to a number			if (isNaN(x)) {				return NaN;			}			return x >= 0 ? 1 : -1;		}	});	return new ScaleUtil();});//# sourceMappingURL=ScaleUtil.js.map
 |