/*
 * Copyright 2009-2011 Quilter's Paradise.  All rights reserved.
 *
 * No portion of this software may be reproduced or used without the expressed written consent of Quilter's Paradise.
 *
 */

/*
 * This function goes to the URL selected by the user in the calculator drop-down menu.
 * Note that the first item in the menu has a null value.  If it is selected, the user remains on the current page.
 */

function goto_calculator_url(calculator)
{
	selection = calculator.options[calculator.selectedIndex].value

	if (selection != "")
	{
		window.location = selection
	}

	return false

} /* End of goto_calculator_url() */
	
/*
 * Function:  isNum
 *
 * Returns true if there is at least one character and all characters are 0-9.
 * Also verifies that if there is a decimal point, there is only one decimal point.
 * Returns false otherwise.
 */

function isNum(value)
{
	/* Check if there is at least one character */
	
	if (value == "")
	{
		return false
	}

	decimal_point = 0
	
	/*
	 * Check each character in turn and verify it is 0-9.
	 * Also, make sure there is at most one decimal point.
	 */
	
	for (i=0; i < value.length; i++)
	{

		if (value.charAt(i) == '.')
		{

			if (decimal_point == 1)
			{
				return false
			}

			decimal_point = 1
			continue
		}

		if (value.charAt(i) < '0')
		{
			return false
		}
		
		if (value.charAt(i) > '9')
		{
			return false
		}
	}
		
	/* It's a valid number */
	
	return true

} /* End of isNum */


/*
 * Function:  nearest_eighth
 *
 * Given a number, it rounds up to the nearest eighth of a yard.  It also allows for 1/3 and 2/3.
 * Output is in fractional, not decimal, form.
 *
 */

function nearest_eighth(yardage)
{

	/*
	 * First check to see if the value of yardage is "N/A".  If it is, then return "N/A" for the amount of yardage to be cut.
	 */

	if (yardage == "N/A")
	{
		return("N/A")
	}

	/*
	 * Convert the fractional part of the yardage passed in to a string (e.g., "1/8", "1/2", etc.).
	 * Note that for 1/3 and 2/3, using values such as 0.33 and 0.67 aren't used because when the value being compared exactly equals
	 * 1/3 or 2/3, the comparison won't yield "equals".  Rather, specify the value to compare to as the fraction itself.
	 */

	whole = Math.floor(yardage)
	fraction = yardage - whole
	print_fraction = ""

	if (fraction == 0)
	{
		print_fraction = ""
	}
	else { if (fraction <= 0.125)
	{
		print_fraction = "1/8"
	}
	else { if (fraction <= 0.25)
	{
		print_fraction = "1/4"
	}
	else { if (fraction <= (1/3))
	{
		print_fraction = "1/3"
	}

	else { if (fraction <= 0.375)
	{
		print_fraction = "3/8"
	}
	else { if (fraction <= 0.5)
	{
		print_fraction = "1/2"
	}
	else { if (fraction <= 0.625)
	{
		print_fraction = "5/8"
	}
	else { if (fraction <= (2/3))
	{
		print_fraction = "2/3"
	}
	else { if (fraction <= 0.75)
	{
		print_fraction = "3/4"
	}
	else { if (fraction <= 0.875)
	{
		print_fraction = "7/8"
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
		 */

		print_fraction = ""
		whole++
	}}}}}}}}}} /* End of all if statements */

	/*
	 * If we're dealing with only a fraction of a yard, then don't print the whole number, just the fraction.
	 */

	if (whole == 0)
	{
		whole = ""
	}

	return(whole + " " + print_fraction)

} /* End of nearest_eighth() */

/*
 * Function:  nearest_eighth_dec
 *
 * Given a number, it rounds up to the nearest eighth of a yard.  It also allows for 1/3 and 2/3.
 * Output is in decimal, not fractional, form.
 *
 */

function nearest_eighth_dec(yardage)
{

	/*
	 * First check to see if the value of yardage is "N/A".  If it is, then return "N/A" for the amount of yardage to be cut.
	 */

	if (yardage == "N/A")
	{
		return("N/A")
	}

	/*
	 * Convert the fractional part of the yardage passed in to a string (e.g., "1/8", "1/2", etc.).
	 */

	whole = Math.floor(yardage)
	fraction = yardage - whole
	print_fraction = 0

	if (fraction == 0)
	{
		print_fraction = 0
	}
	else { if (fraction <= 0.125)
	{
		print_fraction = 0.125
	}
	else { if (fraction <= 0.25)
	{
		print_fraction = 0.25
	}
	else { if (fraction <= (1/3))
	{
		print_fraction = 0.33
	}

	else { if (fraction <= 0.375)
	{
		print_fraction = 0.375
	}
	else { if (fraction <= 0.5)
	{
		print_fraction = 0.5
	}
	else { if (fraction <= 0.625)
	{
		print_fraction = 0.625
	}
	else { if (fraction <= (2/3))
	{
		print_fraction = 0.67
	}
	else { if (fraction <= 0.75)
	{
		print_fraction = 0.75
	}
	else { if (fraction <= 0.875)
	{
		print_fraction = 0.875
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
		 */

		print_fraction = 0
		whole++
	}}}}}}}}}} /* End of all if statements */

	/*
	 * If we're dealing with only a fraction of a yard, then don't print the whole number, just the fraction.
	 */

	if (whole == 0)
	{
		whole = 0
	}

	return(whole + print_fraction)

} /* End of nearest_eighth_dec() */

/*
 * Function:  ValConversion
 *
 * This function is called from the Fabric Measurement Conversion form.  If the inches value is provided, then convert it into yards
 * (in both fractional and decimal form.  If the decimal yards value is given, then convert it into inches and in fractional yards form.
 * Finally, if the fractional yardage value is provided, then convert it into inches and in decimal yardage value form.
 *
 * Calculated inches are rounded up to the nearest inch.  Calculated yardage values, whether decimal or fractional form, are rounded up
 * to the nearest eighth of a yard.
 */

function ValConversion(form)
{

	/* If the inches value is provided, convert into yards */

	if ( form.inches.value != "")
	{
		inches_to_nearest_eighth(form)
		return false
	}

	/* If the decimal yard value is provided, convert into inches and fractional yard */

	if ( form.decimal.value != "")
	{
		yards_to_inches(form)
		return false
	}

	/* if the fractional yard value is provided, convert into inches and decimal yard */

	if ( form.fraction.value != "")
	{
		frac_yards_to_inches(form)
		return false
	}

	/* No value was provided so issue an error message to the user */

	alert("You must enter either an inches value, a yardage value in decimal form, or a yardage value in fractional form")

	return false

} /* End of ValConversion() */

/*
 * Function:  inches_to_nearest_eighth
 *
 * Given a number expressed in inches, it rounds up to the nearest eighth of a yard.  It also allows for 1/3 and 2/3.
 * Output is in decimal and fractional, form.
 *
 */

function inches_to_nearest_eighth(form)
{

	/*
	 * First check to see if the value of inches is a number.
	 */

	if (!isNum(form.inches.value))
	{
		alert("Invalid inches value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}

	/*
	 * Convert the fractional part of the yardage passed in to a string (e.g., "1/8", "1/2", etc.).
	 */

	decimal = form.inches.value / 36
	whole = Math.floor(decimal)
	rem_inches = form.inches.value - (whole * 36)
	fraction_dec = rem_inches / 36

	if (fraction_dec == 0)
	{
		fraction_dec = ""
		fraction = ""
	}
	else { if (fraction_dec <= 0.125)
	{
		fraction_dec = ".125"
		fraction = "1/8"
	}
	else { if (fraction_dec <= 0.25)
	{
		fraction_dec = ".25"
		fraction = "1/4"
	}
	else { if (fraction_dec <= (1/3))
	{
		fraction_dec = ".33"
		fraction = "1/3"
	}

	else { if (fraction_dec <= 0.375)
	{
		fraction_dec = ".375"
		fraction = "3/8"
	}
	else { if (fraction_dec <= 0.5)
	{
		fraction_dec = ".5"
		fraction = "1/2"
	}
	else { if (fraction_dec <= 0.625)
	{
		fraction_dec = ".625"
		fraction = "5/8"
	}
	else { if (fraction_dec <= (2/3))
	{
		fraction_dec = ".67"
		fraction = "2/3"
	}
	else { if (fraction_dec <= 0.75)
	{
		fraction_dec = ".75"
		fraction = "3/4"
	}
	else { if (fraction_dec <= 0.875)
	{
		fraction_dec = ".875"
		fraction = "7/8"
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than ).875.  The fraction then becomes null.
		 */

		fraction_dec = ""
		fraction = ""
		whole++
	}}}}}}}}}} /* End of all if statements */

	/*
	 * If we're dealing with only a fraction of a yard, then don't print the whole number, just the fraction.
	 */

	if (whole == 0)
	{
		whole = ""
	}

	/*
	 * Update the form's output fields.  The color of the text boxes is changed as a visual indicator that
	 * these are output fields.  That is, coloring the output fields makes it clear which field was used as
	 * input and which are for output.
	 */

	form.decimal.value = whole + fraction_dec
	form.decimal.style.backgroundColor = "#f7f5b8"

	form.fraction.value = whole + " " + fraction
	form.fraction.style.backgroundColor = "#f7f5b8"
	
	return false

} /* End of inches_to_nearest_eighth() */

/*
 * Function:  ClearInchesToYardageForm()
 *
 * Clears the InchesToYardageForm.  All it currently does is change the background color of the output text boxes back to white.
 */
 
function ClearInchesToYardageForm(form)
{

	form.inches.style.backgroundColor = "#ffffff"
	form.decimal.style.backgroundColor = "#ffffff"
	form.fraction.style.backgroundColor = "#ffffff"

	return false

} / * End of ClearInchesToYardageForm() */

/*
 * Function:  ClearInchesToYardageFields()
 *
 * When the user selects a text field to enter a value into, the other two fields are automatically cleared.  Additionally, the background
 * colors of all the fields are reset to white.  The reason for this function is so that the user can perform multiple conversions without
 * having to first clear the other fields.  This is because the first populated field is assumed to be the one that we want to convert.  By
 * clearing the other fields, we've now guaranteed that the field the user has selected will be populated first.
 */

function ClearInchesToYardageFields(form, field)
{

	/* First, set all the background colors to white */

	form.inches.style.backgroundColor = "#ffffff"
	form.decimal.style.backgroundColor = "#ffffff"
	form.fraction.style.backgroundColor = "#ffffff"

	/*
	 * The value of the input variable called field is the field that's been selected.  Set the other two fields to null.
	 */

	if ( field == 1 )
	{
		form.decimal.value = ""
		form.fraction.value = ""
	}

	if ( field == 2 )
	{
		form.inches.value = ""
		form.fraction.value = ""
	}

	if ( field == 3 )
	{
		form.inches.value = ""
		form.decimal.value = ""
	}

	return false

} / * End of ClearInchesToYardageForm() */

/*
 * Function:  yards_to_inches
 *
 * Given a number in decimal yardage form, it converts the yardage to inches and to yardage in fractional form.
 *
 */

function yards_to_inches(form)
{

	/*
	 * First check to see if the value of yardage is a number.
	 */

	if (!isNum(form.decimal.value))
	{
		alert("Invalid yardage value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}

	/* Convert to inches (rounded up to the nearest inch) */

	inches = form.decimal.value * 36
	inches = Math.ceil(inches)

	/*
	 * Convert the fractional part of the yardage passed in to a string (e.g., "1/8", "1/2", etc.).
	 */

	whole = Math.floor(form.decimal.value)
	fraction_dec = form.decimal.value - whole

	if (fraction_dec == 0)
	{
		fraction_dec = ""
		fraction = ""
	}
	else { if (fraction_dec <= 0.125)
	{
		fraction_dec = ".125"
		fraction = "1/8"
	}
	else { if (fraction_dec <= 0.25)
	{
		fraction_dec = ".25"
		fraction = "1/4"
	}
	else { if (fraction_dec <= (1/3))
	{
		fraction_dec = ".33"
		fraction = "1/3"
	}

	else { if (fraction_dec <= 0.375)
	{
		fraction_dec = ".375"
		fraction = "3/8"
	}
	else { if (fraction_dec <= 0.5)
	{
		fraction_dec = ".5"
		fraction = "1/2"
	}
	else { if (fraction_dec <= 0.625)
	{
		fraction_dec = ".625"
		fraction = "5/8"
	}
	else { if (fraction_dec <= (2/3))
	{
		fraction_dec = ".67"
		fraction = "2/3"
	}
	else { if (fraction_dec <= 0.75)
	{
		fraction_dec = ".75"
		fraction = "3/4"
	}
	else { if (fraction_dec <= 0.875)
	{
		fraction_dec = ".875"
		fraction = "7/8"
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than ).875.  The fraction then becomes null.
		 */

		fraction_dec = ""
		fraction = ""
		whole++
	}}}}}}}}}} /* End of all if statements */

	/*
	 * If we're dealing with only a fraction of a yard, then don't print the whole number, just the fraction.
	 */

	if (whole == 0)
	{
		whole = ""
	}

	/*
	 * Update the form's output fields.  The color of the text boxes is changed as a visual indicator that
	 * these are output fields.  This was also done should the future enhancement described in the comments for
	 * the function above are done.  That is, coloring the output fields makes it clear which field was used as
	 * input and which are for output.
	 */

	form.inches.value = inches
	form.inches.style.backgroundColor = "#f7f5b8"

	form.fraction.value = whole + " " + fraction
	form.fraction.style.backgroundColor = "#f7f5b8"
	
	return false

} /* End of yards_to_inches() */


/*
 * Function:  frac_yards_to_inches()
 *
 * Given a number in fractional yardage form, it converts the yardage to inches and to yardage in decimal form.
 *
 */

function frac_yards_to_inches(form)
{

	input_value = form.fraction.value

	/*
	 * Delete leading and trailing blanks
	 */

	i = input_value.indexOf(" ")

	while ( i == 0 )
	{

		input_value = input_value.replace(" ", "")
		i = input_value.indexOf(" ")
	}

	i = input_value.length

	while ( (i > 0) && (input_value.charAt(i - 1) == " ") )
	{

		input_value = input_value.substring(0, i-1)
		i = input_value.length
	}

	/*
	 * Ensure that the entered value conforms to one of the following:
	 *
	 * 1.  Whole number
	 * 2.  Fraction
	 * 3.  Whole number + fraction
	 */

	fraction_regexp1 = /^[0-9]+$/
	fraction_regexp2 = /^[0-9]+\/[0-9]+$/
	fraction_regexp3 = /^[0-9]+[ ]+[0-9]+\/[0-9]+$/

	if ( !fraction_regexp1.test(input_value) && !fraction_regexp2.test(input_value) && !fraction_regexp3.test(input_value) )
	{
		alert("Invalid fractional value entered.  Examples of valid values are:  2, 3/8, 1 3/4")
		return false
	}

	/*
	 * By replacing a blank between the whole number and the fraction with a plus sign, we can use the eval() function to figure out
	 * the number's decimal equivalent.
	 */

	input_value = input_value.replace(" ", "+")

	decimal = eval(input_value)

	/* Round to nearest hundredth - i.e., two decimal places */

	decimal = Math.round(decimal * 100) / 100

	form.decimal.value = decimal
	form.decimal.style.backgroundColor = "#f7f5b8"

	/* Convert to inches (rounded up to the nearest inch) */

	inches = decimal * 36
	inches = Math.ceil(inches)

	form.inches.value = inches
	form.inches.style.backgroundColor = "#f7f5b8"


} /* End of frac_yards_to_inches() */

/*
 * Function:  ValPiecesToYardageForm
 *
 * Validates the fields entered by the user in the input form.
 *
 * Returns true if all the fields in the form have been validated.
 * Returns false otherwise.
 */

function ValPiecesToYardageForm(InputForm)
{
 

	/* Validate the entered fabric width */
	
	if (!isNum(InputForm.Fabric_Width.value))
	{
		alert("Invalid fabric width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (InputForm.Fabric_Width.value == 0)
	{
		alert("Fabric width must be non-zero.")
		return false
	}


	/* Validate the entered width */
	
	if (!isNum(InputForm.Width.value))
	{
		alert("Invalid width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (InputForm.Width.value == 0)
	{
		alert("Width must be non-zero.")
		return false
	}
	
	/* Validate the entered length */
	
	if (!isNum(InputForm.Length.value))
	{
		alert("Invalid length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (InputForm.Length.value == 0)
	{
		alert("Length must be non-zero.")
		return false
	}

	/*
	 * Don't allow a width that is bigger than the fabric width.
	 * There's a trick being used ... by dividing by one, we're forcing javascript to change the type
	 * of the variables from text to integer.  Otherwise, the comparison will be based on ASCII
	 * values and won't work correctly.
	 */
	
	if ((InputForm.Width.value / 1) > (InputForm.Fabric_Width.value / 1))	{
		alert("Width must not be greater than the width of the fabric.")
		return false
	}

	
	/* Validate the entered number of pieces */
	
	if (!isNum(InputForm.NumPieces.value))
	{
		alert("Invalid number of pieces value entered.  Enter at least one digit and all digits must be 0-9.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (InputForm.NumPieces.value == 0)
	{
		alert("Number of pieces must be non-zero.")
		return false
	}

	/* Don't allow a decimal point */
	
	if (InputForm.NumPieces.value.indexOf(".") >= 0)
	{
		alert("Number of pieces cannot contain a decimal point.")
		return false
	}

	/*	
	 * All fields have been validated.  Now calculate the yardage amount.
	 *
	 * yardage1 is the answer when cutting the smaller piece as W x L.
	 * yardage2 is the answer when cutting the smaller piece as L x W.
	 */
	
	x = Math.floor(InputForm.Fabric_Width.value / InputForm.Width.value)

	if (x == 0)
	{
		yardage1 = "N/A"
	}
	else
	{
		width_inches = Math.ceil(InputForm.NumPieces.value / x) * InputForm.Length.value
		yardage1 = width_inches / 36
		yardage1 = yardage1.toFixed(2)
	}

	x = Math.floor(InputForm.Fabric_Width.value / InputForm.Length.value)

	if (x == 0)
	{
		yardage2 = "N/A"
	}
	else
	{
		width_inches = Math.ceil(InputForm.NumPieces.value / x) * InputForm.Width.value
		yardage2 = width_inches / 36
		yardage2 = yardage2.toFixed(2)
	}


	x = document.getElementById('results_num_yards1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(yardage1)
 	x.appendChild(y)


	x = document.getElementById('results_piece_width1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(InputForm.Width.value)
 	x.appendChild(y)

	x = document.getElementById('results_piece_length1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(InputForm.Length.value)
 	x.appendChild(y)

	x = document.getElementById('results_num_yards2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(yardage2)
 	x.appendChild(y)

	x = document.getElementById('results_piece_width2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(InputForm.Length.value)
 	x.appendChild(y)

	x = document.getElementById('results_piece_length2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(InputForm.Width.value)
 	x.appendChild(y)

	/*
	 * Determine how much yardage needs to be cut to the nearest 1/8 of a yard.
	 */

	yards_to_cut1 = nearest_eighth(yardage1)
	yards_to_cut2 = nearest_eighth(yardage2)

	x = document.getElementById('results_yards_to_cut1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(yards_to_cut1)
 	x.appendChild(y)

	x = document.getElementById('results_yards_to_cut2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(yards_to_cut2)
 	x.appendChild(y)

	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */
	
	return false

} /* End ValPiecesToYardageForm */


/*
 * Function:  ClearPiecesToYardageForm
 *
 * This function clears the form of all calculated/outputted values.
 */

function ClearPiecesToYardageForm()
{

	x = document.getElementById('results_num_yards1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)


	x = document.getElementById('results_piece_width1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_length1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_yards_to_cut1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)


	x = document.getElementById('results_num_yards2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_width2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_length2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_yards_to_cut2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	return true


} /* End of ClearPiecesToYardageForm() */


/*
 * Function:  ValPieceCountForm
 *
 * Validates the fields entered by the user in the inputs table and calculates the number of pieces of a given size
 * that can be gotten out of a larger piece of fabric whose dimensions are also given.
 *
 */

function ValPieceCountForm(PieceCountForm)
{

	piece_width = PieceCountForm.piece_width.value
	piece_length = PieceCountForm.piece_length.value
	large_piece_width = PieceCountForm.large_piece_width.value
	large_piece_length = PieceCountForm.large_piece_length.value

	/* Validate the entered width of small piece */
	
	if (!isNum(piece_width))
	{
		alert("Invalid width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (piece_width == 0)
	{
		alert("Width must be non-zero.")
		return false
	}
	
	/* Validate the entered length of small piece */
	
	if (!isNum(piece_length))
	{
		alert("Invalid length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (piece_length == 0)
	{
		alert("Length must be non-zero.")
		return false
	}

	/* Validate the entered width of large piece */
	
	if (!isNum(large_piece_width))
	{
		alert("Invalid width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (large_piece_width == 0)
	{
		alert("Width must be non-zero.")
		return false
	}
	
	/* Validate the entered length of large piece */
	
	if (!isNum(large_piece_length))
	{
		alert("Invalid length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (large_piece_length == 0)
	{
		alert("Length must be non-zero.")
		return false
	}

	/*	
	 * All fields have been validated.  Now calculate the the number of pieces.
	 *
	 * num_pieces1 is the answer when cutting the smaller piece as W x L.
	 * num_pieces2 is the answer when cutting the smaller piece as L x W.
	 */
	
	x = Math.floor(large_piece_width / piece_width)
	y = Math.floor(large_piece_length / piece_length)
	num_pieces1 = x * y



	x = Math.floor(large_piece_width / piece_length)
	y = Math.floor(large_piece_length / piece_width)
	num_pieces2 = x * y

	x = document.getElementById('results_num_pieces1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(num_pieces1)
 	x.appendChild(y)


	x = document.getElementById('results_piece_width1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(piece_width)
 	x.appendChild(y)

	x = document.getElementById('results_piece_length1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(piece_length)
 	x.appendChild(y)

	x = document.getElementById('results_num_pieces2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(num_pieces2)
 	x.appendChild(y)

	x = document.getElementById('results_piece_width2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(piece_length)
 	x.appendChild(y)

	x = document.getElementById('results_piece_length2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(piece_width)
 	x.appendChild(y)
	
	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */
	
	return false

} /* End ValPieceCountForm() */

/*
 * Function:  ClearPieceCountForm
 *
 * This function clears the form of all calculated/outputted values.
 */

function ClearPieceCountForm()
{

	x = document.getElementById('results_num_pieces1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_width1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_length1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_num_pieces2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_width2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('results_piece_length2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	return true	

} /* End of ClearPieceCountForm() */

/*
 * Function:  ValYardageForm
 *
 * Validates the fields entered by the user in the Yardage form which is part of the batting and backing calculator.
 * The function outputs how much yardage of fabric, whose width of fabric is an input, is needed given the width and length
 * dimensions of the quilt.  An overage value is also an input with its default being zero.  Overage is added to each of the 4
 * sides of the quilt; in other words, twice the overage value is added to the width and to the length.  Overage is generally needed
 * for backing if the quilt will be quilted on a Longarm/Midarm machine.  The extra backing along each side of the quilt is used
 * to mount the quilt on the machine and so the machine is able to quilt the quilted area of the quilt.
 *
 * Two calculations are performed:  the first is where the width and length of the quilt are as specified (along with any overage) and
 * the second is where the width and length of the quilt are reversed.  The idea is that the backing or batting can be positioned
 * either way.  (The exception is if the backing material's design is directional but that would be something the user would have to decide.)
 * The user can then purchase the least amount of fabric for each calculated yardage amount.
 *
 */

function ValYardageForm(YardageForm)
{

	/* Validate the entered fabric width */
	
	if (!isNum(YardageForm.Fabric_Width.value))
	{
		alert("Invalid fabric width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (YardageForm.Fabric_Width.value == 0)
	{
		alert("Fabric width must be non-zero.")
		return false
	}
 
	/* Validate the entered width */
	
	if (!isNum(YardageForm.Width.value))
	{
		alert("Invalid width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (YardageForm.Width.value == 0)
	{
		alert("Width must be non-zero.")
		return false
	}
	
	/* Validate the entered length */
	
	if (!isNum(YardageForm.Length.value))
	{
		alert("Invalid length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (YardageForm.Length.value == 0)
	{
		alert("Length must be non-zero.")
		return false
	}

	/* Validate the entered overage.  Note that a value of zero is allowed (it is the default value for the field). */
	
	if (!isNum(YardageForm.Overage.value))
	{
		alert("Invalid overage value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	

	/*	
	 * All fields have been validated.  Now calculate the yardage amount.
	 * Note that the yardage needed is rounded up to the nearest eighth after being calculated.
	 * Delete any calculated yardage already in the table.
	 * (Note that at most only one calculated yardage will be in the table; the first time through this
	 * function, there will be none.  Hence, deleting the first child is sufficient.)
	 *
	 * The variable 'left' is the amount of the quilt in the width direction that has to be covered by the fabric.
	 * If the quilt's width (including overage) is greater than the width of the fabric, then the backing
	 * needs to be pieced (i.e., sewn together).  When sewing together, 1/4" from each piece of fabric is used to
	 * create a seam.  So, we go through the for loop as many times as it takes to cover the quilt in the width direction.
	 */

	left = (YardageForm.Width.value * 1) + (2 * YardageForm.Overage.value)

	for ( i = 1; ; i++)
	{

		/* Multiplying by 1 casts the variable into a number from being a text variable */

		togo = left - (YardageForm.Fabric_Width.value * 1)

		if ( togo <= 0 )
		{
			break
		}

		/* A seam is needed so add 1 inch to what's left.  (1/2 inch for each of the two pieces being joined on the seam.) */

		left = togo + 1
	}
	
	length_in_yards = ((YardageForm.Length.value * 1) + (2 * YardageForm.Overage.value)) / 36

	yardage_needed = length_in_yards * i

	yardage_needed_dec = nearest_eighth_dec(yardage_needed)
	yardage_needed = nearest_eighth(yardage_needed)

	/*
	 * For convenience to the user, include how many inches the yardage is equivalent to.  This was done because batting is often measured using a tape
	 * measure and not a cutting mat.
	 *
	 * The function nearest_eighth_dec returns .33 for 1/3 and .67 for 2/3.  If these values are used, then the result looks strange.
	 * (1/3 will be 11.88 inches and 2/3 will be 24.12 inches.)  So, change these values to their exact value before outputting.
	 */

	if ((yardage_needed_dec - .33) == Math.floor(yardage_needed_dec))
	{
		yardage_needed_dec = Math.floor(yardage_needed_dec) + 1/3
	}

	if ((yardage_needed_dec - .67) == Math.floor(yardage_needed_dec))
	{
		yardage_needed_dec = Math.floor(yardage_needed_dec) + 2/3
	}

	yardage_needed = yardage_needed + " (" + yardage_needed_dec * 36 + " inches)"

	x = document.getElementById('yardage1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	/* Output the result */

	y=document.createTextNode(yardage_needed + " when width is " + YardageForm.Width.value + " and length is " + YardageForm.Length.value)
 	x.appendChild(y)

	/*
	 * Now reverse the length and width and calculate the yardage needed.  The for loop behaves as above.
	 */

	left = (YardageForm.Length.value * 1) + (2 * YardageForm.Overage.value)

	for ( i = 1; ; i++)
	{

		/* Multiplying by 1 casts the variable into a number from being a text variable */

		togo = left - (YardageForm.Fabric_Width.value * 1)

		if ( togo <= 0 )
		{
			break
		}

		/* A seam is needed so add 1 inch to what's left.  (1/2 inch for each of the two pieces being joined on the seam.) */

		left = togo + 1
	}

	length_in_yards = ((YardageForm.Width.value * 1) + (2 * YardageForm.Overage.value)) / 36

	yardage_needed = length_in_yards * i

	yardage_needed_dec = nearest_eighth_dec(yardage_needed)
	yardage_needed = nearest_eighth(yardage_needed)

	/*
	 * For convenience to the user, include how many inches the yardage is equivalent to.  This was done because batting is often measured using a tape
	 * measure and not a cutting mat.
	 *
	 * The function nearest_eighth_dec returns .33 for 1/3 and .67 for 2/3.  If these values are used, then the result looks strange.
	 * (1/3 will be 11.88 inches and 2/3 will be 24.12 inches.)  So, change these values to their exact value before outputting.
	 */

	if ((yardage_needed_dec - .33) == Math.floor(yardage_needed_dec))
	{
		yardage_needed_dec = Math.floor(yardage_needed_dec) + 1/3
	}

	if ((yardage_needed_dec - .67) == Math.floor(yardage_needed_dec))
	{
		yardage_needed_dec = Math.floor(yardage_needed_dec) + 2/3
	}

	yardage_needed = yardage_needed + " (" + yardage_needed_dec * 36 + " inches)"

	x = document.getElementById('yardage2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	/* Output the result */

	y=document.createTextNode(yardage_needed + " when width is " + YardageForm.Length.value + " and length is " + YardageForm.Width.value)
 	x.appendChild(y)

	/*
	 * CalculatorMenu is a form (a drop-down menu to be specific) used to navigate between the calculator web pages.
	 * The width and length form items are hidden from the user and are used to pass the quilt's width and length
	 * to other calculators that can make use of them.  This is so the user doesn't have to remember and re-enter this information.
	 */

	document.CalculatorMenu.Width.value = YardageForm.Width.value
	document.CalculatorMenu.Length.value = YardageForm.Length.value

	
	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */
	
	return false

} /* End ValYardageForm */


/*
 * Function:  ClearYardageForm
 *
 * This function clears the form of all calculated/outputted values.
 */

function ClearYardageForm()
{

	x = document.getElementById('yardage1')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('yardage2')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)
	return true


} /* End of ClearYardageForm() */


/*
 * Function:  count_char
 *
 * This function counts the number of occurrences of a particular character.  It is used by the Die Cut calculator.
 *
 */
 
 function count_char(search_char, search_text)
 {
 	/*
 	 * count - counts the number of occurrences of the character.
 	 * pos - keeps track of the position in the string to be searched.
 	 *
 	 * Search through the entered text looking for the concerned character.
 	 */
 	
 	var count = 0
 	var pos = search_text.indexOf(search_char)
 	
 	while (pos != -1)
 	{
 		count++
 		pos = search_text.indexOf(search_char, pos+1)
 	}
 	
 	/*
 	 * Find the table entry (i.e., cell) for the character.  If there is an entry already there, delete it first.
 	 * Otherwise, the new value will simply be added to the end of the existing entry.
 	 */
 	
 	var table_entry = document.getElementById("DIECUTCHAR_" + search_char)
 	 
 	if (table_entry.firstChild)
 	{
 		table_entry.removeChild(table_entry.firstChild)
	}

	var count_entry = document.createTextNode(count)
 	table_entry.appendChild(count_entry)
 	
 	return count

} /* End of count_char() */
 
/*
 * Function:  count_all_chars
 *
 * This function counts the number of occurrences of each alphanumeric character in the text entered by the user.
 * It is used by the Die Cut calculator.
 */

function count_all_chars()
{

	/*
	 * The array die_cut_chars contains a list of all the allowed characters that the die cut machine can make.
	 * To add a new character, simply add it to the end of the list and be sure to add an entry (cell) in the
	 * diecutchar_count_table.  There is no case sensitivity - i.e., no need to distinguish between upper and
	 * lower case.
	 */
	 
	var die_cut_chars = new Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9")
	var total_chars = 0

	/*
	 * Convert the text entered into the text box to upper case.  Then only need to search once versus
	 * twice for upper then lower case.
	 */

	var entered_text = document.DieCutTextForm.DieCutTextArea.value.toUpperCase();

	/*
	 * For each die cut character, determine the number of occurrences in the entered text.
	 */
	 
	for ( i = 0; i < die_cut_chars.length; i++ )
	{
		total_chars += count_char(die_cut_chars[i], entered_text)
	}
	
	/*
 	 * Find where to put the total character count.  If there is an entry already there, delete it first.
 	 * Otherwise, the new value will simply be added to the end of what's already there.
 	 */
 	
 	var total_die_cut_chars_entry = document.getElementById("TotalDieCutChars")
 	 
 	if (total_die_cut_chars_entry.firstChild)
 	{
 		total_die_cut_chars_entry.removeChild(total_die_cut_chars_entry.firstChild)
	}

	var new_total_count_entry = document.createTextNode(total_chars)
 	total_die_cut_chars_entry.appendChild(new_total_count_entry)

	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculations will disappear.
	 */
	
	return false


} /* End of count_all_chars() */


/*
 * Function:  ClearDieCutForm
 *
 * This function zeroes all the calculated/outputted counters.
 */

function ClearDieCutForm()
{

	var die_cut_chars = new Array("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9")

	/*
	 * Set the count for each character to zero.  Setting the value to null or a blank messes up the solid lines in the table so need to reset to some non-blank value.
	 */
	 
	for ( i = 0; i < die_cut_chars.length; i++ )
	{
		table_entry = document.getElementById("DIECUTCHAR_" + die_cut_chars[i])
 	 
 		if (table_entry.firstChild)
 		{
 			table_entry.removeChild(table_entry.firstChild)
		}

		count_entry = document.createTextNode("0")
	 	table_entry.appendChild(count_entry)
	}

	/*
	 * Set the total number of characters to zero and the text area containing the entered text to null.
	 */

	x = document.getElementById('TotalDieCutChars')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("0")
 	x.appendChild(y)

	x = document.getElementById('DieCutTextArea')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)
	return true


} /* End of ClearDieCutForm() */


/*
 * Function:  ValBindingForm
 *
 * This function is used by the Binding calculator.  Given a quilt's width and length along with the width of the binding strip,
 * it determines how much yardage is needed for the binding.  Another output is how many binding strips need to be cut from the fabric.
 * This is useful to the quilter so they don't have to figure out how many strips to cut from the calculated yardage.
 */

function ValBindingForm(BindingForm)
{

	/* Validate the entered width */
	
	if (!isNum(BindingForm.Width.value))
	{
		alert("Invalid quilt width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BindingForm.Width.value == 0)
	{
		alert("Quilt width must be non-zero.")
		return false
	}

	/* Validate the entered fabric length */
	
	if (!isNum(BindingForm.Length.value))
	{
		alert("Invalid quilt length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BindingForm.Length.value == 0)
	{
		alert("Quilt length must be non-zero.")
		return false
	}
 	
	/* Validate the entered fabric width */
	
	if (!isNum(BindingForm.Fabric_Width.value))
	{
		alert("Invalid fabric width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BindingForm.Fabric_Width.value == 0)
	{
		alert("Fabric width must be non-zero.")
		return false
	}

	/*	
	 * All fields have been validated.  First, calculate the binding length.
	 * Basically, add 10 inches to the overall perimeter.  (Ten inches is a rule of thumb that provides some extra margin in practice.)
	 */
 
	x = document.getElementById('binding length')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	binding_length = (2 * BindingForm.Width.value) + (2 * BindingForm.Length.value) + 10

	y=document.createTextNode(binding_length)
 	x.appendChild(y)

	/*
	 * Determine what the user selected as the strip width.
	 * The form returns the index (starting with zero) of the selected item.  The algorithm
	 * below assumes that the entries that the user can select from start with the value 2
	 * and monotonically increase by 0.25.
	 */

	index = BindingForm.Strip_Width.selectedIndex
	strip_width = (index * 0.25) + 2

	/*
	 * First, do the calculations for "regular" binding strips.
	 *	
	 * The yardage amount is determined by first calculating how many strips
	 * will be needed.  Then, multiply by the strip_width and convert inches to yards.
	 */
 
	num_strips = Math.ceil(binding_length / BindingForm.Fabric_Width.value)

	yards = (num_strips * strip_width) / 36

	fraction = yards - Math.floor(yards)

	/* Determine closest 1/8 of a fraction that is higher than the fraction */

	print_yards = Math.floor(yards)

	if (fraction == 0)
	{
		print_fraction = ""
	}
	else { if (fraction <= 0.125)
	{
		print_fraction = "1/8"
	}
	else { if (fraction <= 0.25)
	{
		print_fraction = "1/4"
	}
	else { if (fraction <= 0.33)
	{
		print_fraction = "1/3"
	}

	else { if (fraction <= 0.375)
	{
		print_fraction = "3/8"
	}
	else { if (fraction <= 0.5)
	{
		print_fraction = "1/2"
	}
	else { if (fraction <= 0.625)
	{
		print_fraction = "5/8"
	}
	else { if (fraction <= 0.67)
	{
		print_fraction = "2/3"
	}
	else { if (fraction <= 0.75)
	{
		print_fraction = "3/4"
	}
	else { if (fraction <= 0.875)
	{
		print_fraction = "7/8"
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
		 */

		print_fraction = ""
		print_yards++
	}}}}}}}}}} /* End of all if statements */
	
	x = document.getElementById('yardage')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	/*
	 * Output binding yardage needed.  If the number of yards is less than 1, don't print the whole number,
	 * just the fraction.
	 */

	if (print_yards == 0)
	{
		print_yardage = print_fraction
	}
	else
	{
		print_yardage = print_yards + " " + print_fraction
	}

	y=document.createTextNode(print_yardage)
 	x.appendChild(y)

	/* Now output number of strips that need to be cut. */

	x = document.getElementById('number strips')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(num_strips)
 	x.appendChild(y)

	/*
	 * Now do the calculations for bias binding strips.
	 *
	 * Essentially, the algorithm is to determine the square area of fabric needed to do the bias binding strips.
	 * To that we add 100 square inches as both margin and so that the user cuts a large enough square/rectangle
	 * so they aren't cutting really short bias strips near the corners of the square/rectangle.
	 *
	 */

	/* Output the strip binding length */

	x = document.getElementById('bias binding length')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(binding_length)
 	x.appendChild(y)


	/* Square piece of fabric calculations */

	area = (binding_length * strip_width) + 100
	square_side = Math.sqrt(area)
	square_side = Math.ceil(square_side)

	x = document.getElementById('square_size')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(square_side)
 	x.appendChild(y)

	/* Fabric cut off bolt calculations */

	yards = (num_strips * strip_width) / 36
	fraction = yards - Math.floor(yards)

	/* Determine closest 1/8 of a fraction that is higher than the fraction */

	print_yards = Math.floor(yards)

	if (fraction == 0)
	{
		print_fraction = ""
	}
	else { if (fraction <= 0.125)
	{
		print_fraction = "1/8"
	}
	else { if (fraction <= 0.25)
	{
		print_fraction = "1/4"
	}
	else { if (fraction <= 0.33)
	{
		print_fraction = "1/3"
	}

	else { if (fraction <= 0.375)
	{
		print_fraction = "3/8"
	}
	else { if (fraction <= 0.5)
	{
		print_fraction = "1/2"
	}
	else { if (fraction <= 0.625)
	{
		print_fraction = "5/8"
	}
	else { if (fraction <= 0.67)
	{
		print_fraction = "2/3"
	}
	else { if (fraction <= 0.75)
	{
		print_fraction = "3/4"
	}
	else { if (fraction <= 0.875)
	{
		print_fraction = "7/8"
	} else {

		/*
		 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
		 */

		print_fraction = ""
		print_yards++
	}}}}}}}}}} /* End of all if statements */

	/*
	 * Output bias binding yardage needed.  If the number of yards is less than 1, don't print the whole number,
	 * just the fraction.
	 */

	if (print_yards == 0)
	{
		print_yardage = print_fraction
	}
	else
	{
		print_yardage = print_yards + " " + print_fraction
	}
	
	x = document.getElementById('bolt_yardage')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(print_yardage)
 	x.appendChild(y)


	/*
	 * CalculatorMenu is a form (a drop-down menu to be specific) used to navigate between the calculator web pages.
	 * The width and length form items are hidden from the user and are used to pass the quilt's width and length
	 * to other calculators that can make use of them.  This is so the user doesn't have to remember and re-enter this information.
	 */

	document.CalculatorMenu.Width.value = BindingForm.Width.value
	document.CalculatorMenu.Length.value = BindingForm.Length.value
	
	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */
	
	return false

} /* End ValBindingForm() */


/*
 * Function:  ClearBindingForm
 *
 * This function clears the form of all calculated/outputted values.
 */

function ClearBindingForm()
{

	x = document.getElementById('binding length')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('number strips')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('yardage')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('bias binding length')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('square_size')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	x = document.getElementById('bolt_yardage')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
 	x.appendChild(y)

	return true


} /* End of ClearBindingForm() */


/*
 * Function:  ValBorderForm
 *
 * Validates the fields entered by the user in the border calculator form and performs the necessary calculations.
 * Passed to it is the form with the input data fields and output data fields.
 *
 */

function ValBorderForm(BorderForm)
{

	/*
	 * Set the maximum number of borders.  This value must equal the number of borders in the HTML form
	 * and the value of max_borders in ClearBorderForm().
	 *
	 * The idea is that a quilt may have more than one border.  Most quilts have no more than 2 or 3 borders; hence, it was felt
	 * that setting a limit of 5 would more than suffice in practice.
	 */

	max_borders = 5

	/* Amount to add (in inches) for an unfinished border above and beyond a finished border.  This amount is added to the width of the border strip
	 * in calculating the yardage needed for the border.
	 *
	 * The amount to add is 1/2 inch.  When piecing 2 pieces of fabric together, standard practice is to allocate a 1/4 inch seam allowance
	 * to each piece of fabric.  Since there are 2 sides to the strip of border fabric, you have a total of 1/2 inch.  A finished border is
	 * when the border has been pieced; unfinished is before it's been pieced.
	 */

	unfinished_adder = 0.5

	/* Validate the entered width of the quilt. */
	
	if (!isNum(BorderForm.Width.value))
	{
		alert("Invalid quilt width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BorderForm.Width.value == 0)
	{
		alert("Quilt width must be non-zero.")
		return false
	}

	/* Validate the entered length of the quilt. */
	
	if (!isNum(BorderForm.Length.value))
	{
		alert("Invalid quilt length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BorderForm.Length.value == 0)
	{
		alert("Quilt length must be non-zero.")
		return false
	}
 	
	/* Validate the entered fabric width */
	
	if (!isNum(BorderForm.Fabric_Width.value))
	{
		alert("Invalid fabric width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (BorderForm.Fabric_Width.value == 0)
	{
		alert("Fabric width must be non-zero.")
		return false
	}

	/*
	 * Validate the user-entered border widths.  There can be up to max_borders altogether.
	 * As soon as a border width is empty, you've gotten them all.  (The user need only enter as many borders as they need.
	 * There must be at least one border present, though.
	 */

	for ( num_borders = 1; num_borders <= max_borders; num_borders++ )
	{

		this_border_width = eval("BorderForm.Border" + num_borders + "Width.value")

		if (this_border_width == "")
		{
			break
		}

		/* Check the entered border width */
		
		if (!isNum(this_border_width))
		{
			alert("Invalid border width width value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
			return false
		}
	
		/* Don't allow a value of zero */
	
		if (this_border_width == 0)
		{
			alert("Border width must be non-zero.")
			return false
		}

	} /* end for loop */

	if ( num_borders == 1 )
	{
		alert("You must enter at least one border width starting with Border 1.")
		return false
	}

	/*
	 * Now calculate and output the yardage for each of the borders starting with the innermost border first (Border 1) and working out.
	 *
	 * border_width = this is how long the border is in the width direction of the quilt.  It increases as you move to the next-most outer border.
	 * border_length = this is how long the border is in the length direction of the quilt.  It, too, increases as you move to the next-most outer border.
	 *
	 * The initial values of these variables are the quilt's dimensions as entered by the user.
	 *
	 * border_strip_width = the width of the current border.
	 */

	border_width = BorderForm.Width.value
	border_length = BorderForm.Length.value

	for ( i = 1; i < num_borders; i++)
	{

		/*
		 * First determine the overall length of the FINISHED border strip.
		 *
		 * The dividing by 1 is to convert all the variables from text to numbers.
		 */

		border_strip_width = eval("BorderForm.Border" + i + "Width.value")

		total_length = (2 * (border_length/1) ) + (2 * ((border_width/1) + (2 * (border_strip_width/1))))

		/*
		 * Borders can be mitred or not mitred at the corners.  (Mitred is the preferred method by quilters since it looks much better.)
		 *
		 * Check to see if the user selected mitre borders.  If so, add the current border width again (4 times, once for each corner).
		 */

		for (j = 0; j < BorderForm.mitre.length; j++)
		{
			if (BorderForm.mitre[j].checked)
			{
				mitre_value = BorderForm.mitre[j].value
			}
		}

		if (mitre_value == "mitre")
		{
			total_length += 2 * (2 * (border_strip_width/1))
		}

		strip_width = (border_strip_width/1) + (unfinished_adder/1)

		/*
		 * To determine the number of strips, first determine the effective fabric width.  What you want to imagine is that you're cutting
		 * strips that are the width of fabric in length.  However, they need to be pieced together, in effect, to form a strip that is
		 * equal in length to the value of the variable "total_length".  Piecing can be done in a "straight" fashion - essentially butt end of
		 * the strip joining the butt end of another strip - or in a "mitre" fashion - along a 45 deg angle.  In the "straight" fashion,
		 * you lose an amount equal to the value of "unfinished_addr".  Remember, you're piecing at both ends of a given strip.
		 * In a "mitre" fashion, you're losing an amount equal to the width of the unfinished border (which is in the variable "border_strip_width")
		 * times 2 (again, 2 ends of the strip).  The effective length of a strip that you cut off a bolt, then, is equal to the
		 * width of fabric minus what you lose.  Divide that into the total length to get the number of strips you must cut off the bolt.
		 */

		straight_loss = unfinished_adder
		mitre_loss = 2* (border_strip_width/1)

		straight_num_strips = Math.ceil(total_length / (BorderForm.Fabric_Width.value - straight_loss) )
		mitre_num_strips = Math.ceil(total_length / (BorderForm.Fabric_Width.value - mitre_loss) )

		straight_yards = (straight_num_strips * strip_width) / 36
		mitre_yards = (mitre_num_strips * strip_width) / 36

		/* Output the width of the strip to be cut for this border */

		strip_width_output = "StripWidth" + i

		x = document.getElementById(strip_width_output)
	 	if (x.firstChild)
 		{
 			x.removeChild(x.firstChild)
		}

		y=document.createTextNode((border_strip_width/1) + 0.5)
 		x.appendChild(y)


		/* Output the results for straight piecing */

		yards = straight_yards
		fraction = yards - Math.floor(yards)

		num_strips = straight_num_strips

		/* Determine closest 1/8 of a fraction that is higher than the fraction */

		print_yards = Math.floor(yards)

		if (fraction == 0)
		{
			print_fraction = ""
		}
		else { if (fraction <= 0.125)
		{
			print_fraction = "1/8"
		}
		else { if (fraction <= 0.25)
		{
			print_fraction = "1/4"
		}
		else { if (fraction <= 0.33)
		{
			print_fraction = "1/3"
		}

		else { if (fraction <= 0.375)
		{
			print_fraction = "3/8"
		}
		else { if (fraction <= 0.5)
		{
			print_fraction = "1/2"
		}
		else { if (fraction <= 0.625)
		{
			print_fraction = "5/8"
		}
		else { if (fraction <= 0.67)
		{
			print_fraction = "2/3"
		}
		else { if (fraction <= 0.75)
		{
			print_fraction = "3/4"
		}
		else { if (fraction <= 0.875)
		{
			print_fraction = "7/8"
		} else {

			/*
			 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
			 */

			print_fraction = ""
			print_yards++
		}}}}}}}}}} /* End of all if statements */

		/* Find the item in the form to output the result to */
	
		output = "Border" + i + "Yardage"

		x = document.getElementById(output)
	 	if (x.firstChild)
 		{
 			x.removeChild(x.firstChild)
		}

		/*
		 * Output border yardage needed.  If the number of yards is less than 1, don't print the whole number,
		 * just the fraction.
		 */

		if (print_yards == 0)
		{
			print_yardage = print_fraction
		}
		else
		{
			print_yardage = print_yards + " " + print_fraction
		}

		y=document.createTextNode(print_yardage)
 		x.appendChild(y)

		/* Output the number of strips to be cut for this border */

		num_strips_output = "NumStrips" + i

		x = document.getElementById(num_strips_output)
	 	if (x.firstChild)
 		{
 			x.removeChild(x.firstChild)
		}

		y=document.createTextNode(num_strips)
 		x.appendChild(y)

		/* Output the results for mitre piecing */

		yards = mitre_yards
		fraction = yards - Math.floor(yards)

		num_strips = mitre_num_strips

		/* Determine closest 1/8 of a fraction that is higher than the fraction */

		print_yards = Math.floor(yards)

		if (fraction == 0)
		{
			print_fraction = ""
		}
		else { if (fraction <= 0.125)
		{
			print_fraction = "1/8"
		}
		else { if (fraction <= 0.25)
		{
			print_fraction = "1/4"
		}
		else { if (fraction <= 0.33)
		{
			print_fraction = "1/3"
		}

		else { if (fraction <= 0.375)
		{
			print_fraction = "3/8"
		}
		else { if (fraction <= 0.5)
		{
			print_fraction = "1/2"
		}
		else { if (fraction <= 0.625)
		{
			print_fraction = "5/8"
		}
		else { if (fraction <= 0.67)
		{
			print_fraction = "2/3"
		}
		else { if (fraction <= 0.75)
		{
			print_fraction = "3/4"
		}
		else { if (fraction <= 0.875)
		{
			print_fraction = "7/8"
		} else {

			/*
			 * Need to add 1 to the whole number since the fractional part is greater than 7/8.  The fraction then becomes null.
			 */

			print_fraction = ""
			print_yards++
		}}}}}}}}}} /* End of all if statements */

		/* Find the item in the form to output the result to */
	
		output = "Border" + i + "Yardage" + "Mitre"

		x = document.getElementById(output)
	 	if (x.firstChild)
 		{
 			x.removeChild(x.firstChild)
		}

		/*
		 * Output border yardage needed.  If the number of yards is less than 1, don't print the whole number,
		 * just the fraction.
		 */

		if (print_yards == 0)
		{
			print_yardage = print_fraction
		}
		else
		{
			print_yardage = print_yards + " " + print_fraction
		}

		y=document.createTextNode(print_yardage)
 		x.appendChild(y)

		/* Output the number of strips to be cut for this border */

		num_strips_output = "NumStrips" + i + "Mitre"

		x = document.getElementById(num_strips_output)
	 	if (x.firstChild)
 		{
 			x.removeChild(x.firstChild)
		}

		y=document.createTextNode(num_strips)
 		x.appendChild(y)

		/* Adjust the border width and length for the next pass through the loop */
	
		border_width = (border_width/1) + (2 * (border_strip_width/1))
		border_length = (border_length/1) + (2 * (border_strip_width/1))

	} /* end for loop */

	/*
	 * Now output the overall border width and length.
	 */

	x = document.getElementById("OverallWidth")
 	if (x.firstChild)
	{
		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(border_width)
	x.appendChild(y)

	x = document.getElementById("OverallLength")
 	if (x.firstChild)
	{
		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(border_length)
	x.appendChild(y)

	/*
	 * CalculatorMenu is a form (a drop-down menu to be specific) used to navigate between the calculator web pages.
	 * The width and length form items are hidden from the user and are used to pass the quilt's width and length
	 * to other calculators that can make use of them.  This is so the user doesn't have to remember and re-enter this information.
	 */

	document.CalculatorMenu.Width.value = border_width
	document.CalculatorMenu.Length.value = border_length

	return false


} /* End ValBorderForm() */


/*
 * Function:  ClearBorderForm
 *
 * This function clears the border form of all calculated/outputted values.
 */

function ClearBorderForm()
{

	/*
	 * Set the maximum number of borders.  This value must equal the number of borders in the HTML form and the value of max_borders in ValBorderForm().
	 */

	max_borders = 5

	for (i = 1; i <= max_borders; i++)
	{

		id = "StripWidth" + i

		x = document.getElementById(id)
	 	if (x.firstChild)
	 	{
	 		x.firstChild.data = ""
		}

		id = "Border" + i + "Yardage"

		x = document.getElementById(id)
	 	if (x.firstChild)
	 	{
	 		x.firstChild.data = ""
		}

		id = "Border" + i + "Yardage" +"Mitre"

		x = document.getElementById(id)
	 	if (x.firstChild)
	 	{
	 		x.firstChild.data = ""
		}

		id = "NumStrips" + i

		x = document.getElementById(id)
	 	if (x.firstChild)
	 	{
	 		x.firstChild.data = ""
		}

		id = "NumStrips" + i + "Mitre"

		x = document.getElementById(id)
	 	if (x.firstChild)
	 	{
	 		x.firstChild.data = ""
		}

	}

	x = document.getElementById("OverallWidth")
	if (x.firstChild)
	{
		x.removeChild(x.firstChild)
	}

	y = document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById("OverallLength")
	if (x.firstChild)
	{
		x.removeChild(x.firstChild)
	}

	y = document.createTextNode("")
	x.appendChild(y)

	/*
	 * Set the width and height values in the form that takes the user to another calculator page.
	 * Since the borders are "zero'ed out", set the width and length values to the values of the quilt
	 * before the borders were added.
	 */

	document.CalculatorMenu.Width.value = BorderForm.Width.value
	document.CalculatorMenu.Length.value = BorderForm.Length.value

	return true


} /* End of ClearBorderForm() */

/*
 * Function:  ValSquareInSquareForm
 *
 * This function calculates all the key dimensions of a square in a square block
 * given either the finished inside square length or the finished outside square length as a starting point.
 *
 * There are 5 key dimensions in working with a square in a square:
 *
 * ISFL - Inside Square Finished Length
 * ISUL - Inside Square Unfinished Length
 * OSFL - Outside Square Finished Length
 * OSUL - Outside Square Unfinished Length
 * CSSL - Corner Square Side Length
 *
 * A form is passed to this function in which either ISFL or OSFL is specified.  The function then calculates the other 4
 * dimensions from the given length.
 *
 * The 4 basic formulas used are:
 *
 * IUSL = ISFL + 0.5
 * OSFL = ISFL * sqrt(2)
 * OSUL = OSFL + 0.5
 * CSSL = (ISFL / sqrt(2)) + 0.8536
 *
 * Note: 0.8536 is often rounded to 7/8 in books.  Basically, the CSSL is from an unfinished piece.  The ISFL / sqrt(2) part of the formula
 * is for a finished piece.  If you add 1/4" around all 3 sides of the finished triangle to form the unfinished triangle, you'll find that the
 * unfinished side length is 0.8536" longer than its corresponding finished side length.
 *
 * The inputted dimension is always a multiple of 1/8".  We also want the outputs to be a multiple of 1/8".  Rounding is necessary to accomplish this.
 */

function ValSquareInSquareForm(form)
{

	/*
	 * The variable 'magic' is a magic number as described in the comments above.
	 */

	magic = 0.8536

	/* Determine the inputted length from its whole and fractional parts */

	input_length = (form.whole_length.value * 1) + (eval(form.fraction_length.value) * 1)

 	/*
	 * Determine which dimension was specified and perform the necessary calculations.  The variable length_type is not initialized
	 * because the passed form always has a checked radio button.
	 */

	for (i = 0; i < form.length_type.length; i++)
	{ 
		if (form.length_type[i].checked)
		{
			length_type = form.length_type[i].value
			break
		}
	}

	if (length_type == "ISFL")
	{
		isfl = input_length
		isul = isfl + 0.5
		osfl = isfl * Math.sqrt(2)
		osul = osfl + 0.5
		cssl = (isfl / Math.sqrt(2)) + magic
	}

	if (length_type == "OSFL")
	{
		osfl = input_length
		osul = osfl + 0.5
		isfl = osfl / Math.sqrt(2)
		isul = isfl + 0.5
		cssl = (isfl / Math.sqrt(2)) + magic
	}

	/*
	 * Round all the values to the nearest 1/8" and output to the web page.  Note that if the whole number is zero,
	 * we don't want to output a zero but rather nothing.
	 */

	isfl = Math.round(isfl/0.125) * 0.125
	isfl_output = nearest_eighth(isfl)

	isul = Math.round(isul/0.125) * 0.125
	isul_output = nearest_eighth(isul)

	osfl = Math.round(osfl/0.125) * 0.125
	osfl_output = nearest_eighth(osfl)

	osul = Math.round(osul/0.125) * 0.125
	osul_output = nearest_eighth(osul)

	cssl = Math.round(cssl/0.125) * 0.125
	cssl_output = nearest_eighth(cssl)

	x = document.getElementById('ISFL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(isfl_output)
 	x.appendChild(y)

	x = document.getElementById('ISUL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(isul_output)
 	x.appendChild(y)

	x = document.getElementById('OSFL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(osfl_output)
 	x.appendChild(y)

	x = document.getElementById('OSUL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(osul_output)
 	x.appendChild(y)

	x = document.getElementById('CSSL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode(cssl_output)
 	x.appendChild(y)

	return false

} /* End of ValSquareInSquareForm() */


/*
 * Function:  ClearSquareInSquareForm
 *
 * This function clears the Square in a Square form of all calculated/outputted values.
 */

function ClearSquareInSquareForm()
{

	x = document.getElementById('ISFL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById('ISUL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById('OSFL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById('OSUL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById('CSSL_Result')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	return true

} /* End of ClearSquareInSquareForm() */

/*
 * Function:  ValSetInTriangleForm
 *
 * This calculator determines the size of a square to cut to create both unfinished Half Square Triangles (HSTs) and unfinished Quarter Square Triangles (QSTs)
 * given the size of the finished square to which these triangles correspond.
 */

function ValSetInTriangleForm(form)
{

	/* Validate the entered finished square's side length */
	
	if (!isNum(form.FinishedSquareLength.value))
	{
		alert("Invalid finished square length value entered.  Enter at least one digit, all digits must be 0-9, and there can be at most one decimal point.")
		return false
	}
	
	/* Don't allow a value of zero */
	
	if (form.FinishedSquareLength.value == 0)
	{
		alert("Finished square length must be non-zero.")
		return false
	}

	/*
	 * Half Square Triangle (HST) calculations
	 *
	 * The side of the square that is to be cut to form the HSTs is the hypotenuse of the finished square's side plus 7/8" rounded to the nearest eighth of an inch.
	 * Adding 7/8" provides the necessary seam allowance since the triangles being cut will be unfinished.
	 *
	 * Note:  this function was developed much earlier than the Square in a Square function above.  As described in the comments
	 * for the Square in a Square calculator, the "magic number" is often rounded to 7/8 which is what was done here.
	 */

	side = form.FinishedSquareLength.value / Math.sqrt(2)
	side = side + 0.875
	side = nearest_eighth(side)

	/*
	 * If side is rounded to nearest 1/3 or 2/3, round up to nearest eighth.
	 * This is because nearest_eighth_dec includes 1/3 and 2/3 in rounding and we don't want that for this particular function.
	 */

	side = side.replace("1/3", "3/8")
	side = side.replace("2/3", "3/4")

	x = document.getElementById('HSTSquareToCutLength')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	/* Output the result */

	y=document.createTextNode(side)
 	x.appendChild(y)
	
	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */

	/*
	 * Quarter Square Triangle (QST) calculations
	 *
	 * The side of the square that is to be cut to form the QSTs is the length of the finished square's side plus 1 1/4" rounded to the nearest eighth of an inch.
	 * Adding 1 1/4" provides the necessary seam allowance since the triangles being cut will be unfinished.
	 * 1 1/4" is another "magic" type of number.  The derivation is via geometry ... imagine a right triangle (with the opposite angles both being 45 degrees)
	 * and another triangle outside of it where each of this second triangle's sides is 1/4" away from the inner triangle's sides.
	 * (The 1/4" figure is the seam allowance.)  The hypotenuse of the outer triangle is 1 1/4" longer than the hypotenuse of the inner triangle.
	 */

	side = form.FinishedSquareLength.value * Math.sqrt(2)
	side = side + 1.25
	side = nearest_eighth(side)

	/*
	 * If side is rounded to nearest 1/3 or 2/3, round up to nearest eighth.
	 * This is because nearest_eighth_dec includes 1/3 and 2/3 in rounding and we don't want that for this particular function.
	 */

	side = side.replace("1/3", "3/8")
	side = side.replace("2/3", "3/4")

	x = document.getElementById('QSTSquareToCutLength')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	/* Output the result */

	y=document.createTextNode(side)
 	x.appendChild(y)
	
	/*
	 * Need to return false (not true).  If return true, then values in form and
	 * the calculated yardage put into the table will disappear.
	 */

	return false

} /* End ValSetInTriangleForm() */	



/*
 * Function:  ClearSetInTriangleForm
 *
 * This function clears the Set in Triangle form of all calculated/outputted values.
 */

function ClearSetInTriangleForm()
{

	x = document.getElementById('HSTSquareToCutLength')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	x = document.getElementById('QSTSquareToCutLength')
 	if (x.firstChild)
 	{
 		x.removeChild(x.firstChild)
	}

	y=document.createTextNode("")
	x.appendChild(y)

	return true

} /* End of ClearSetInTriangleForm() */
