// Globals
var conversionType = "";
var trace=false;

function Runswitch()

/*********************************************************************************
*   This routine switches the boolean value "trace" between true and false. This *
*   is in turn used throughout the script whether to output on not alert messages*
*   used as trace statements for debugging purposes. The trace is turned on by a *
*   checkbox on the input form.                                                  *
**********************************************************************************
*/

{
if  (trace) {trace=false} else {trace=true}
}

function checknum(inputval)
{
if  (trace) alert("checknum "+inputval);
var str = "" + inputval;
var num = 0;
var val = 0;

val = parseFloat(inputval);
if (isNaN(val))
    {
    ;
    }
else
    {
    num = parseFloat(str);
    }
return num;   
}

function checkit(avalue)
{
if  (trace) alert("checkit "+avalue);

var val = checknum(avalue);
if  (val == 0)
    {
    alert("The value you entered is not a number, please enter valid number");
    val = 1;
    }
else
    {
    if  (val < 0)
        {
        alert("The value entered was a negative value, please enter a positive value");
        }
    }
document.FormList.destvalue.value ="";
document.FormList.sourcevalue.value = val;
return val;
}

function resetform()
{   
if  (trace) alert("resetform ");
    document.FormList.sourcevalue.value = 1;
    document.FormList.destvalue.value = 1;
    SourceIndex = document.FormList.FromSelection.selectedIndex;
    DestIndex   = document.FormList.ToSelection.selectedIndex;
    document.FormList.sourceunits.value = datalist[SourceIndex].name;
    document.FormList.destunits.value = datalist[DestIndex].name;
    document.FormList.FromSelection.options[SourceIndex].selected = true;
    document.FormList.ToSelection.options[DestIndex].selected = true;
}


function SetSource(obj)
{
if  (obj.FromSelection.options.selectedIndex < 0 || obj.FromSelection.options.selectedIndex >
							obj.FromSelection.options.length )
    {
    obj.FromSelection.options.selectedIndex = 1;
    }
obj.destvalue.value ="";
SourceIndex = obj.FromSelection.options.selectedIndex;
while (datalist[SourceIndex].basis == 0)
    {SourceIndex++}
obj.FromSelection.options.SelectedIndex = SourceIndex;  
obj.sourceunits.value = datalist[SourceIndex].name;
}

function SetDest(obj)
{
if  (obj.ToSelection.options.selectedIndex < 0 || obj.ToSelection.options.selectedIndex >
							obj.ToSelection.options.length )
    {
    obj.ToSelection.options.selectedIndex = 1;
    }
obj.destvalue.value = "";
DestIndex = obj.ToSelection.options.selectedIndex;
while (datalist[DestIndex].basis == 0)
    {DestIndex++}
obj.ToSelection.options.SelectedIndex = DestIndex;  
obj.destunits.value = datalist[DestIndex].plural;
}

function roundOff(svalue, precision)

/*********************************************************************************
*   This routine takes a numeric value and returns the value rounded to the      *
*   number of significant digits specified by 'precision'. This provides the     *
*   facility to round any number format retaining decimal places as needed       *
*   unlike the built in function which only rounds to the nearest integer.       *
*   Note. svalue = string form of numeric value including decimal but no exponent*
*         precison = numeric integer showing number of significant digits        *
**********************************************************************************
*/
{	
if  (trace) alert("roundOff svalue "+svalue+" precision "+precision);

var power = 0;
var decpoint = 0;
var value = 0;

svalue = "" + svalue;
precision = parseInt(precision,10); //gets integer value of precision
if  (precision < 1 )
	{return "******";}
	else
	{
	decpoint = svalue.indexOf(".");
 	if  (decpoint != -1)
        {
        if  (svalue.length -1 > precision)
			{
           value = parseFloat(svalue);
			power = (precision - decpoint); 	
		    value *= Math.pow(10,power);
	 		value = Math.round(value);
			value /= Math.pow(10,power); //this returns the decimal to the starting place
            svalue = "" + value;
			}
		}
	else
	    {
        if  (svalue.length > precision)
    		{
            power = svalue.length - precision;
            value = parseInt(svalue);
    	    value /= Math.pow(10,power);
            value = Math.round(value);
            value *= Math.pow(10,power);
            svalue = "" + value;
			}
		}
    }
if  (trace) alert("roundOff return svalue "+svalue);
return svalue;
}

function accuracy(sinput,accType)
/**********************************************************************************
*   This routine takes a string representing a numeric value with or without an   *
*   an exponent and a format of accuracy required then returns the accuracy of    *
*   the value in terms of the number of significant digits.                       *
*                                                                                 *
*   If "accType" == "A" accuracy is absolute to 10 digits.                        *
*                                                                                 *
*   If "accType" == "S" accuracy is strictly scientific, based on the significant *
*   digits of conversion factors except values which evaluate to 1 times some     *
*   magnitude of 10 which are given an accuracy of 10 digits.                     *
*                                                                                 *
*   The user supplied input value is treated as having infinite                   *
*   (10 digit actual) accuracy)                                                   *
***********************************************************************************
*/
{
if  (trace) alert("accuracy input & Type = "+sinput+" "+accType);

var siz = 0;
var exp = 0;

if  (accType == "A")
    {
    siz = 10;
    }
else
    {
    exp = sinput.indexOf("E");
    dec = sinput.indexOf(".");
        if  (exp != -1)
            {
            siz = exp; // the number sans exponent is 'exp' long but may still contain a decimal 
            }
        else
            {
            siz = sinput.length; // without an exponent, number = 'length' signifcant digits but may have a decimal
            }
        if  (dec != -1)
            {
            siz = siz - 1; // if the number has a decimal reduce the number of digits by 1
            }
        if  (parseFloat(sinput.substring(0,exp)) == 1)
            {
            siz = 10;
            }
    }
if  (trace) alert("accuracy siz = "+siz);
return siz;

}

function normal(astring) 
/*********************************************************************************
*   This routine has been included to allow processing of values greater than    *
*   the maximum value handled by javascript, probably in a 16 bit environment as *
*   anything greater than 10^18 just locks up Netscape Navigator. Since some of  *
*   the values used in some of the tables are larger than this, I was forced to  *
*   write this routine and some of the related routines to handle these large    *
*   values. This was also necessary in order to acheive the correct degree of    *
*   accuracy of the results                                                      *
**********************************************************************************
*/
{
if  (trace) alert("normal "+astring);

var i = 0;          // used as an index for a for loop
var exp = 0;        // used for the index of the "E" of an exponent
var dec = 0;        // used for the index of a decimal point
var num = 0;        // used for as a temporary numeric value of the mantissa
var powerdiff = 0;  // used as the temporary numeric value of exponent when normalizing to 'n.n...' format 
var exponent = 0;   // used as the numeric value of the exponent
var sexponent = ""; // used for a string representation of the exponent
var bstring = "";

astring = "" + astring; // to convert any numeric values to strings
exp = astring.indexOf("E");

//  cannot convert to a numeric as it may be too large, therefore must do it the hard way

if  (exp != -1)                 // index position of an exponent
    {
    sexponent = astring.substring(exp + 1,astring.length);
    exponent = parseInt(sexponent); // exponent now isolated
    astring = astring.substring(0,exp); // astring now holds only the mantissa
    }
else                            // no exponent
    {
    exponent = 0;
    }
num =parseFloat(astring);
if  (isNaN(num))
    {
    alert("Invalid value in internal table, please inform the author giving the 'from' and 'to' units");
    astring = "1.0E0";
    }
else
    { 
    dec = astring.indexOf(".");
    if  (dec != -1)                 //  the mantissa has a decimal
        {
        if  (num < 1) // value less than 1
            {
            astring = astring.substring(dec + 1,astring.length); //get rid of leading zeros before the decimal & the decimal point
            dec = 0;
            powerdiff -= astring.length;
            for (i = 0; i < astring.length ; i++) // get rid of leading zeros after the decimal
                {
                if  (astring.charAt(i) == "0")
                    {
                    ;
                    }
                else
                    {
                    astring = astring.substring(i,astring.length)
                    break;
                    }
                } // end of for loop
            }     // end of if  (num < 1) // value less than 1
        else      // number is >= 1
            {
            astring = astring.substring(0,dec) + astring.substring(dec+1,astring.length)
            powerdiff = -(astring.length - dec);
            }     // end of else for  if  (num < 1) // value less than 1 i.e it is >= 1 or zero
        }  // end of if  (dec != -1)
// at this point astring contains a value without a decimal and powerdiff the adjustment for values
// that had a decimal
// the next two lines standardize the mantissa to a 'n.nnn.....' format and exponent adjustment
    powerdiff += astring.length -1; // the adjustment from standardizing the mantissa to the exponent input
    astring = astring.substring(0,1) + "." + astring.substring(1,astring.length); // change to a standard format of n.nnn
    exponent += powerdiff;
    sexponent = "" + exponent; // check a negative value is converted correctly
    astring = astring +"E"+exponent; // this is the display value of the input factor normalized
    }         // end of else for if (isNaN(num))
return astring;
} // end of normal(astring) function

function formatit(astring,mantissa,exponent,accuracy,formattype)
/*********************************************************************************
*   This routine formats the output value into a form appropriate to the units   *
*   selected, scientific format for SI units, and traditional for old, business  *
*   or scientific units less than 1000. Note that Javascript math operations     *
*   are based on double byte accuracy, but that will still result in some results*
*   with values cosisting of with extra trailing zeros and a final "1" digit or  *
*   alternatively values with up to 20 places with trailing "9's" digits such    *
*   that values are 1*10^-20 too large or too small. This routine corrects these *
*   rounding problems.                                                           *
**********************************************************************************
*/
{
if  (trace) alert("formatit "+astring+" "+mantissa+" "+exponent+" "+accuracy+" "+formattype);

var bstring = "";
var cstring = "";
var dec = 0;

dec = astring.indexOf(".");
if  (formattype == "A" && exponent < 11 && exponent >= 0)
    {
    mantissa *= Math.pow(10,exponent);
    exponent = 0; // just in case it gets used later, we want the correct value
    bstring = "" + mantissa;
    bstring = roundOff(bstring,10);
    dec = bstring.indexOf(".");
    astring = "";
    if  (dec != -1)
        {
        cstring = bstring.substring(dec,bstring.length); // fractional part including the decimal
        bstring = bstring.substring(0,dec);              // integer part
        }
    while  (bstring.length > 3)
        {
        astring = "," +  bstring.substring(bstring.length - 3,bstring.length) + astring; 
        bstring = bstring.substring(0,bstring.length -3);
        }
    astring = bstring.substring(0,bstring.length) + astring + cstring; 
    }
else
    {
    if  ((accuracy < 4 || mantissa == 1) && Math.abs(exponent) < 4)
        {
        mantissa *= Math.pow(10,exponent);
        mantissa = roundOff(mantissa,10);
        exponent = 0; // just in case it gets used later, we want the correct value
        astring = "" + mantissa;
        }
    else
        {
        if  (astring.length == 2 && astring.indexOf(".") == 1)
            {
            astring += "0";
            }
        if  (exponent != 0)
            {
            astring = astring + "E" + exponent;
            }  // end else of 'if  (exponent == 0)'
        }   // end else of 'if  ((accuracy < 4 || mantissa == 1) && Math.abs(exponent) < 4)'
    }     // end of else of 'if  (formattype == "A" && exponent < 11 && exponent >= 0)'
return astring;
} // end of function formatit

function Compute(form)
/*********************************************************************************
*  This routine checks the selections to see if either or both are comment lines *
*  and if so just clears the output fields ready for a valid selection, otherwise*
*  it calls the compute1 function.                                               *
**********************************************************************************
*/

{
if	(datalist[SourceIndex].basis != 0 && datalist[DestIndex].basis != 0)
   	{
if  (trace) alert("Compute 0");
    Compute1(form);
	}
if  (trace) alert("Compute End");
}
/* End of Compute */

function Compute1(obj)
/*********************************************************************************
*   This routine calculates the output conversion factor multiplied by the user  *
*   supplied value to be converted, which defaults to 1.                         *
*   The conversion is 'User input value * ((From unit factor)/(To unit factor)). *                                                         *
**********************************************************************************
*/

{
if  (trace) alert("Compute "+obj);

var svalue1 = " ";   // string representation of 'From' factor
var svalue2 = " ";   // string representation of 'To' factor
var svalue3 = " ";   // string representation of result value
var value3 =0;      // result value working storage 
var acc0 = 0;       // significant digits required in the result 
var acc1 = 0;       // significant digits in the 'From' factor
var acc2 = 0;       // significant digits in the 'To' factor
var exp = 0;        // index of the exponent 
var mantissa1 = " "; //factor 1 significant value
var mantissa2 = " "; //factor 2 significant value
var exponent1 = 0;  //factor 1 exponent
var exponent2 = 0;  //factor 2 exponent
var exponent3 = 0;  //input value exponent
var factorsUsed = 0;//used to store which factors are being used
var formattype = " "; //used to identify the form of result formatting needed

value3 = checkit(obj.sourcevalue.value);
if  (trace) alert("Compute 1");
if  (value3 == 1)
	{
    obj.sourceunits.value = datalist[SourceIndex].name;
	}
else
    {
    obj.sourceunits.value = datalist[SourceIndex].plural;
    }
if  (trace) alert("Compute 2");
if	((datalist[SourceIndex].basis == 1 || datalist[DestIndex].basis == 1) ||
     (datalist[SourceIndex].basis != datalist[DestIndex].basis))
   	{
if  (trace) alert("Compute 3");
     factorsUsed = 1;
     svalue1 = " " + datalist[SourceIndex].factor1;
     svalue2 = " " + datalist[DestIndex].factor1;
	}
else
    {
if  (trace) alert("Compute 4 "+ SourceIndex +" "+DestIndex);
     factorsUsed = 2;
     svalue1 = " " + datalist[SourceIndex].factor2;
if  (trace) alert("Compute 6");
	 svalue2 = " " + datalist[DestIndex].factor2;
if  (trace) alert("Compute 7");
    }
svalue1 = normal(svalue1);
exp = svalue1.indexOf("E");
mantissa1 = 1*(svalue1.substring(0,exp)); // store the mantissa of the value in the 'from' value mantissa
if  (trace) alert("Compute 8");
exponent1 = 1*(svalue1.substring(exp + 1,svalue1.length)); // store the exponent of the value in the 'from' value exponent
if  (trace) alert("Compute 9");
svalue2 = normal(svalue2);
if  (trace) alert("Compute 10");
exp = svalue2.indexOf("E");
mantissa2 = 1*(svalue2.substring(0,exp)); // store the mantissa of the value in the 'to' value mantissa
exponent2 = 1*(svalue2.substring(exp + 1,svalue2.length)); // store the mantissa of the value in the 'to' value mantissa
if  (trace) alert("conversionType= "+conversionType);

if  (conversionType != "D")
    {
    acc1 = accuracy(svalue1,conversionType);
    acc2 = accuracy(svalue2,conversionType);
    formattype = conversionType;
    }
else
    {
    if  (factorsUsed == 1)
        {
        if  (datalist[SourceIndex].usage == "Basis")
            {
            acc1 = accuracy(svalue1,"A");
            formattype = "S";
            }
        else
            {
            acc1 = accuracy(svalue1,"S");
            formattype = "S";
            }
        if  (datalist[DestIndex].usage == "Basis")
            {
            acc2 = accuracy(svalue2,"A");
            formattype = "S";
            }
        else
            {
            acc2 = accuracy(svalue2,"S");
            formattype = "S";
            }
        }
    else
        {
        acc1 = accuracy(svalue1,"A");
        acc2 = accuracy(svalue2,"A");
        formattype = "A";
        }
    }
if  (trace) alert("After setting acc1 & acc2 accuracy - acc1 = "+acc1+" acc2 = "+acc2);
acc0 = Math.min(acc1,acc2);
value3 *= mantissa1/mantissa2; // calculate the dividend of the mantissas
exponent3 = exponent1 - exponent2; // calculate the dividend of the exponents and save them for now
svalue3 = "" + value3;
if  (trace) alert("Before normal "+svalue3+" "+value3+" "+exponent3);
svalue3 = normal(svalue3); // normalize the mantissa value to the 'n.nnn...' format
if  (trace) alert("After normal "+svalue3);
exp = svalue3.indexOf("E"); // we always get an exponent (could be zero) after normalizing
mantissa3 = 1*(svalue3.substring(0,exp)); // store the mantissa of the value in the 'result' value mantissa
exponent3 += parseInt(svalue3.substring(exp+1,svalue3.length)); // store the exponent of the value in the 'result' value exponent
svalue3 = "" + mantissa3;
if  (trace) alert("Before roundOff "+svalue3+" "+mantissa3+" "+exponent3+" "+exp);
svalue3 = roundOff(svalue3,acc0); // round the mantissa result to the correct number of significant digits
if  (trace) alert(svalue3+" "+exponent3+" "+acc1+" "+acc2+" "+acc0);
value3 = parseFloat(svalue3);
acc0 = Math.min(acc0,svalue3.length - 1); // because the mantissa includes a decimal point
svalue3 = formatit(svalue3,value3,exponent3,acc0,formattype);
if  (trace) alert(svalue3+" "+exponent3+" "+acc1+" "+acc2+" "+acc0);
if  (value3 == 1 && exponent3 == 0)
	{
    obj.destunits.value = datalist[DestIndex].name;
	}
else
    {
    obj.destunits.value = datalist[DestIndex].plural;
    }
obj.destvalue.value = svalue3;

}
/*********************** 
*    End of Compute1    *
************************
*/

function writelist()
/*********************************************************************************
*   This routine creates the option list for the specified type of units included*
*   as the second include file in the HTML source file.                          *
**********************************************************************************
*/
{
if  (trace) alert("writelist ");

var i = 0;
var j = datalist.length;
for (i = 0 ; i < j ; i++)
    {
    if (datalist[i].usage == "Basis")
        {selected = " SELECTED";
         
        }
    else
        { selected = " ";
        }
    out = "<OPTION" + selected + ">" + datalist[i].name;
    document.write(out);
        }
}
/*********************** 
*   End of writelist   *
************************
*/

function setAcc(acc) {
    conversionType = acc;
                     }

function writePage()
/*********************************************************************************
* This function writes the web page. It is reusable code that is used by each    *
* separate conversion table to avoid duplication of the same code in each page.  *
* As a result, the calling pages can each be very small.                         *
**********************************************************************************/

{
document.write('<BR>&nbsp;<BR>&nbsp;');
document.write('<CENTER><TABLE BORDER=8 CELLSPACING=5 CELLPADDING=5 COLS=1 WIDTH="90%" BGCOLOR="#000000">');
document.write('<TR ALIGN=CENTER VALIGN=CENTER><TD ALIGN=CENTER VALIGN=CENTER>');
document.write('<FONT SIZE=+1><FONT COLOR="#FFFFFF"><B><U>');
document.write(sTitle + ' Conversions</U></B></FONT></CENTER><CENTER>');
document.write('<B><FONT COLOR="#FFFFFF">Enter a value to be converted or use the default value of ');
document.write('<I>1</I>, select the units to convert <I>from</I> and <I>to</I>. The converted value is ');
document.write('displayed in the <I>To Units</I> fields. For quick selection of units enter ');
document.write('the first character of the unit name while the cursor focus is in the <I>from</I> or ');
document.write('<I>to</I> units tables. Repeated character entry scrolls through all units with ');
document.write('the same first character.</B></FONT></TD></TR></TABLE></CENTER>');
document.write('<FORM NAME="FormList"><CENTER>');
document.write('<TABLE BORDER=4 COLS=3 WIDTH="80%" BGCOLOR=#9F14A7><TR>');
document.write('<TD ALIGN=CENTER><FONT COLOR="#FFFFFF"><B>From Units</TD><TD>&nbsp;</TD>');
document.write('<TD ALIGN=CENTER><FONT COLOR="#FFFFFF"><B>To Units</TD></TR><TR><TD NOWRAP ALIGN=RIGHT>');
document.write('<SELECT NAME="FromSelection" SIZE=10 onchange="SetSource(this.form);Compute(this.form)">');
define();
writelist();
document.write('</SELECT></TD><TD>&nbsp;</TD><TD NOWRAP ALIGN=LEFT>');
document.write('<SELECT NAME="ToSelection" SIZE=10 onchange="SetDest(this.form);Compute(this.form)">');
writelist();
document.write('</SELECT>');
for (var i = 0; i < document.FormList.FromSelection.length; i++)
    {
    if (document.FormList.FromSelection.options[i].defaultSelected == true)
       {
       document.FormList.FromSelection.options[i].selected=true;
       document.FormList.ToSelection.options[i].selected=true;
       }
    }
document.write('</TD></TR><TR><TD ALIGN=RIGHT>');
document.write('<INPUT TYPE="text" NAME="sourcevalue" SIZE="39" MAXLENGTH="20" onblur="Compute(this.form)"><BR>');
document.write('<INPUT TYPE="text" NAME="sourceunits" SIZE="39" MAXLENGTH="30" onblur="Compute(this.form)"></TD>');
document.write('<TD ALIGN=CENTER><FONT SIZE=+2><FONT COLOR="#FFFFFF"><B>&nbsp;=&nbsp;</B></FONT></TD>');
document.write('<TD ALIGN=LEFT>');
document.write('<INPUT TYPE="text" NAME="destvalue"   SIZE="39" MAXLENGTH="20" onblur="Compute(this.form)"><BR>');
document.write('<INPUT TYPE="text" NAME="destunits"   SIZE="39" MAXLENGTH="30" onblur="Compute(this.form)">');
document.write('</TD></TR></TABLE>');
}

function initialize()
{
resetform();
setAcc("D");
defaultStatus=' ';
}
// End the hiding here. -->