/********************************************************************
* Math Text Input Field
* @author CS Wagner <chris@kainaw.com>
* @version 1.1
*********************************************************************
* Javascript to add mathematical functionality to a standard HTML
* text input.
* When a mathematical operator is entered, it will calculate a
* running value and display it.
* Entering '=' will finish all pending calculations.
*********************************************************************
* Note: This is purely a left-to-right calculation.
* Operator precedence is ignored.
* Parenthesis cause a NaN state.
* Any NaN state will propogate through the equation.
*********************************************************************
* USE:
* On the KEYUP event of the text input, call mathFieldKeyUp with
* 'this' as the first argument (no quotes), an integer (minimum
* number of decimal places), and an integer (maximum number of
* decimal places) as the third argument.
*********************************************************************
* EXAMPLE:
* <INPUT TYPE='text' ONKEYUP='javascript:mathFieldKeyUp(this, 2, 2)'>
*********************************************************************/

/**
 * Check to see if a calculation is necessary.
 * If so, calculate everything before the ending math function.
 * @param field	the field to run the calculation on
 * @param mindp	min number of decimal places
 * @param maxdp	max number of decimal places
 **/
function mathFieldKeyUp(field, mindp, maxdp)
{
	if(field.value.length<2) return; // Don't do anything to an empty field

	var functions="+-*/%";

	var equation=field.value.substring(0,field.value.length-1);
	var endChar=field.value.charAt(field.value.length-1);

	if(functions.indexOf(endChar)>-1)
		field.value=solveEquation(equation, mindp, maxdp)+endChar;
	else if(endChar=='=')
		field.value=solveEquation(equation, mindp, maxdp);
}

/**
 * Calculate the math value of an equation.
 * @param equation	the math equation
 * @param mindp	min number of decimals
 * @param maxdp	max number of decimals
 * @return equation's solution
 **/
function solveEquation(equation, mindp, maxdp)
{
	if(maxdp<0) maxdp=0;
	var mult=1;
	for(var i=0; i<maxdp; i++) mult*=10;

	var functions="+-*/%";
	var func='+';
	var oldVal=0;
	var newVal=0;
	var fp=0;
	var ep=0;
	for(ep=0; ep<equation.length; ep++)
	{
		var c=equation.charAt(ep);
		if(functions.indexOf(c)>-1)
		{
			newVal=parseFloat(equation.substring(fp,ep));
			if(fp==ep) newVal=0;
			if(func=='+') oldVal+=newVal;
			else if(func=='-') oldVal-=newVal;
			else if(func=='*') oldVal*=newVal;
			else if(func=='/') oldVal/=newVal;
			else if(func=='%') oldVal%=newVal;
			func=equation.charAt(ep);
			fp=ep+1;
		}
	}
	newVal=parseFloat(equation.substring(fp,ep));
	if(fp==ep) newVal=0;
	if(func=='+') oldVal+=newVal;
	else if(func=='-') oldVal-=newVal;
	else if(func=='*') oldVal*=newVal;
	else if(func=='/') oldVal/=newVal;
	else if(func=='%') oldVal%=newVal;
	oldVal=Math.round(oldVal*mult)/mult;
	return padToMinDP(oldVal, mindp, maxdp);
}

/**
 * Pad a given value to a minimum number of decimal places.
 * @param val	value to pad
 * @param mindp	min number of decimals
 * @param maxdp max number of decimals
 * @return padded value
 **/
function padToMinDP(val, mindp, maxdp)
{
	if(val==NaN) return;
	val=""+val;
	var decimal=val.indexOf(".");
	var integer;
	var fraction;
	if(decimal==-1)
	{
		integer=val;
		fraction="0";
	}
	else
	{
		integer=val.substring(0,decimal);
		fraction=val.substring(decimal+1);
	}
	if(maxdp==0) return integer;
	while(fraction.length<mindp) fraction+="0";
	return integer+"."+fraction;
}

