function addToList(strLabel, strValue, objSelect, selected)
{
	// If selected is 1 then this item should be selected
	if ( selected == 1 )
    objSelect[objSelect.length] = new Option(strLabel, strValue, true);
	else
	  objSelect[objSelect.length] = new Option(strLabel, strValue);
}

// Remove all items from menu
function clearList(objSelect)
{
  var items = objSelect.length;
	
  for (var i = items - 1; i >= 0; i--)
	{
    objSelect.remove(i);
	}
}

function removeFromList(objSelect)
{
  SelectedCounter = objSelect.length;
	
  for (i = 0; i < SelectedCounter; i++)
	{
	  if ( objSelect[i].selected )
		{
		  objSelect[i] = null;
			SelectedCounter--;
			i--;
		}
	}
}

function updateList(action, objForm, sourceID, destID, maxItems)
{
	maxReached = false;
	
	// Default maximum items if not specified that can be added to destination list is 9999
	if ( maxItems == undefined )
	  maxItems = 9999;
		
	sourceList = objForm.elements[sourceID];
	sourceCount = sourceList.length;
	iTotalSouceItems = sourceCount;
 
	destList = objForm.elements[destID];
	destCount = destList.length;
	iTotalDestItems = destCount;

  // Possible options: addAll, add, remove, removeAll
	switch (action)
	{
	  case 'addAll': //add all
			for (i = 0; i < iTotalSouceItems; i++)
			{
				// Add items to destination starting at the next available slot so existing items
  			// are not overwritten
				destList[destCount] = new Option(sourceList[i].text, sourceList[i].value);
				
				// Move to next slot in destination
				destCount++;
			}
			
			// Remove items from source by setting each to null
			for (i = 0; i < iTotalSouceItems; i++)
			{
				sourceList[0] = null;
			}
		break;
    
		case 'add': // Add to destination
		  for (i = 0; i < sourceCount && !maxReached; i++)
			{

				if ( sourceList[i].selected  )
				{
					if ( destList.length + 1 > maxItems )
					  maxReached = true;
					else
					{
						// Add items to destination starting at the next available slot so existing items
						// are not overwritten
						destList[destCount] = new Option(sourceList[i].text, sourceList[i].value);
						
						// Remove item from source list
						sourceList[i] = null;
						
						// Move to next slot in destination
						destCount++;
						
						// Decrement item count in source list
						sourceCount--;
						
						// Decrement source list index since an item was removed
						i--;
					}
				}
			}
		break;

		case 'remove': // Remove from destination
		  for (i = 0; i < destCount; i++)
			{
			  if ( destList[i].selected )
				{
					// Add items to source starting at the next available slot so existing items
			    // are not overwritten
				  sourceList[sourceCount] = new Option(destList[i].text, destList[i].value);
					
					// Remove item from destination list
					destList[i] = null;
					
					// Move to next slot in source
					sourceCount++;
					
					// Decrement item count in destination list
					destCount--;
					
					// Decrement destination list index since an item was removed
					i--;
				}
			}
		break;
    
		case 'removeAll': // remove all from destination
			for (i = 0; i < iTotalDestItems; i++)
			{
				// Add items to source starting at the next available slot so existing items
  			// are not overwritten
			  sourceList[sourceCount] = new Option(destList[i].text, destList[i].value);
				
				// Move to next slot in source
				sourceCount++;
			}

			// Remove items from destination by setting each to null
			for (i = 0; i < iTotalDestItems; i++)
			{
				destList[0] = null;
			}
		break;
  }
	
	// Alert user that the maximum was reached
	if ( maxReached )
	  alert("The maximum items that can be added are: " + maxItems);
}

function removeFromRecipients(objForm, recipientID, contactID, categoryID)
{		
	recipientList = objForm.elements[recipientID];
	recipientCount = recipientList.length;
 
	contactList = objForm.elements[contactID];
	contactCount = contactList.length;
	
	categoryList = objForm.elements[categoryID];
	categoryCount = categoryList.length;

  // Determine the type of record being removed from the recipient list
	// If record is a contact then move to contact list
	// Else move record to category list
	
	CONTACT_TYPE = 1;
	CATEGORY_TYPE = 2;
	
	for (i = 0; i < recipientCount; i++)
	{
		if ( recipientList[i].selected )
		{
			// Extract the two fields from recipient record (Format: type|recordID
			data = recipientList[i].value.split("|");
			
			if (data[0] == CONTACT_TYPE)
			{
				// Add items to source starting at the next available slot so existing items
			  // are not overwritten
			  contactList[contactCount] = new Option(recipientList[i].text, recipientList[i].value);
				
				// Move to next slot in contactList
			  contactCount++;
			}
			else
			{
				// Add items to source starting at the next available slot so existing items
			  // are not overwritten
			  categoryList[categoryCount] = new Option(recipientList[i].text, recipientList[i].value);
				
				// Move to next slot in categoryList
			  categoryCount++;
			}
					
			// Remove item from recipientList list
			recipientList[i] = null;				
			
			// Decrement item count in recipientList list
			recipientCount--;
			
			// Decrement recipientList index since an item was removed
			i--;
		}
	}		
}

//function updateYarnList(action, objForm, sourceID, destID, maxItems, skeinsID, yardsID)
function updateYarnList(action, objForm, sourceID, destID, maxItems, skeinsID)
{
	maxReached = false;
	
	// Default maximum items if not specified that can be added to destination list is 9999
	if ( maxItems == undefined )
	  maxItems = 9999;
	
	//if ( skeinsID != undefined && yardsID != undefined )
	if ( skeinsID != undefined )
	{
	  skeins = objForm.elements[skeinsID];
	}
	
	sourceList = objForm.elements[sourceID];
	sourceCount = sourceList.length;
	iTotalSouceItems = sourceCount;
 
	destList = objForm.elements[destID];
	destCount = destList.length;
	iTotalDestItems = destCount;
  
	//if ( skeinsID != undefined && yardsID != undefined )
	if ( skeinsID != undefined )
	{		
		// Skeins and yards must be filled out and be numeric values
//		if ( trim(skeins.value).length == 0 || trim(yards.value).length == 0 ||
//				 !isNumeric(skeins.value) || !isNumeric(yards.value) )
		if ( trim(skeins.value).length == 0 || !isNumeric(skeins.value) )
		{
			//alert("The Skeins and Yards fields are required when assigning a yarn.\nAlso make sure these fields only contain numbers.");
			alert("The Skeins field is required when assigning a yarn.\nAlso make sure it contains a numeric value.");
			return;
		}
	}
	
  // Possible options: addAll, add, remove, removeAll
	switch (action)
	{
		case 'add': // Add to destination
		  for (i = 0; i < sourceCount && !maxReached; i++)
			{

				if ( sourceList[i].selected  )
				{
					if ( destList.length + 1 > maxItems )
					  maxReached = true;
					else
					{
						// Add items to destination starting at the next available slot so existing items
						// are not overwritten						
						
						// sourceList[i].value = yarn_id|yards_per_skein
						yarnData = sourceList[i].value.split("|");
						
						if ( yarnData.length < 2 )
						{
							alert("Yarn data is invalid.");
							return;
						}
						
						// Calculate yarn cost and update Yarn Cost field on form
						calculateYarnCost(objForm, yarnData[2], skeins.value);
						
						// Calculate total materials cost and update Total Materials Cost field on form
						totalMaterialsCost(objForm);						
						
						// Calculate total yards by taking skeins used * yards per skein
						totalYards = yarnData[1] * skeins.value;
						formattedTotalYards = new NumberFormat(totalYards);
						formattedTotalYards.setPlaces(2);
						
						formattedSkeins = new NumberFormat(skeins.value);
						formattedSkeins.setPlaces(2);
						
						// Update total yards used in formula
						updateTotalYards(objForm, totalYards);
						
						//destList[destCount] = new Option(sourceList[i].text + "|" + formattedSkeins.toFormatted() + "|" + formattedTotalYards.toFormatted(), yarnData[0] + "|" + formattedSkeins.toFormatted() + "|" + formattedTotalYards.toFormatted());
						// Format:
						// Text  = Skeins | TotalYards | Yarn name
						// Value = Yarn ID | Skeins | TotalYards | YardsPerSkein | CostPerSkein
						destList[destCount] = new Option(formattedSkeins.toFormatted() + "|" + formattedTotalYards.toFormatted() + "|" + sourceList[i].text, yarnData[0] + "|" + formattedSkeins.toFormatted() + "|" + formattedTotalYards.toFormatted() + "|" + yarnData[1] + "|" + yarnData[2]);
						
						// Clear the skeins and yards fields
						skeins.value = "";
						yards.value = "0";
						
						// Remove item from source list
						sourceList[i] = null;
						break;
						// Move to next slot in destination
						destCount++;
						
						// Decrement item count in source list
						sourceCount--;
						
						// Decrement source list index since an item was removed
						i--;
					}
				}
			}
		break;

		case 'remove': // Remove from destination
		  for (i = 0; i < destCount; i++)
			{
			  if ( destList[i].selected )
				{
					// Add items to source starting at the next available slot so existing items
			    // are not overwritten
					
					// Format:
					// Yarn name
					// Yarn ID|Yards
					
					yarnData = destList[i].text.split("|");
					
					if ( yarnData.length == 3 )
					  listText = yarnData[2];
					else
					  listText = destList[i].text;
					
					yarnData = destList[i].value.split("|");
					
					if ( yarnData.length == 5 )
					  listValue = yarnData[0] + "|" + yarnData[3] + "|" + yarnData[4];
					else
					  listValue = destList[i].value;
          
					// Calculate yarn cost and update Yarn Cost field on form
					// Note the negative skeins parameter so the yarn cost will be subtracted rather than added
					calculateYarnCost(objForm, yarnData[4], -yarnData[1]);
						
					// Calculate total materials cost and update Total Materials Cost field on form
					totalMaterialsCost(objForm);
					
					// Update total yards used in formula
					updateTotalYards(objForm, -yarnData[2]);
						
				  sourceList[sourceCount] = new Option(listText, listValue);
					
					// Remove item from destination list
					destList[i] = null;
					
					// Move to next slot in source
					sourceCount++;
					
					// Decrement item count in destination list
					destCount--;
					
					// Decrement destination list index since an item was removed
					i--;
				}
			}
		break;
    
		case 'removeAll': // remove all from destination
			for (i = 0; i < iTotalDestItems; i++)
			{
				// Add items to source starting at the next available slot so existing items
  			// are not overwritten
			  sourceList[sourceCount] = new Option(destList[i].text, destList[i].value);
				
				// Move to next slot in source
				sourceCount++;
			}

			// Remove items from destination by setting each to null
			for (i = 0; i < iTotalDestItems; i++)
			{
				destList[0] = null;
			}
		break;
  }
	
	// Alert user that the maximum was reached
	if ( maxReached )
	  alert("The maximum items that can be added are: " + maxItems);
}

function searchSelectItems(objSelect, strSearch)
{
  for (i = 0; i < objSelect.length; i++)
	{		
		if ( objSelect[i].text.toLowerCase() == strSearch.toLowerCase() )
		  return true; // found match
	}
	
	// No match found
	return false;
}

function swapImage(elementID, imagePath)
{
  targetImg = document.getElementById(elementID);
	
	targetImg.src = imagePath;
}

function keyHandler(evt, objForm)
{
  evt = (evt) ? evt : event;
  var charCode = (evt.charCode) ? evt.charCode : ((evt.which) ? evt.which : evt.keyCode);
  
	if ( charCode == 13 )
	{
    checkForm(objForm);
		return false;
  }
}

function showPage(pageNum, objForm)
{
	 if ( objForm.page != undefined )
	  objForm.page.selectedIndex = pageNum;
		
  objForm.submit();
}

function isNumeric(sText)
{
  var validChars = "0123456789";
  var isNumber = true;
	var decimalCount = 0;
  var ch;

  for (i = 0; i < sText.length && isNumber == true; i++) 
  { 
    ch = sText.charAt(i);
		
    if ( validChars.indexOf(ch) == -1 )
    {
			// Makre sure only 1 decimal point exists
			if ( ch == "." && decimalCount == 0 )
			  decimalCount++;
			else
        isNumber = false;
    }
  }
  
	return isNumber;
}

function formatAsCurrency(objTxtField, minNum, maxNum, defaultNum)
{	
  var errorFlag = false;
	var errMsg = "";
  var strNum = new String(objTxtField.value);
	
  // If a dollar sign already exists at the beginning of the string and has a length of at least 2
	// then see if everything after the dollar sign is a number. If it is then there's nothing
	// to do, return success
	if ( strNum.indexOf("$") == 0 && strNum.length >= 2 )
	{
	  // Strip commas and dollar sign to see if it's a number
	  if ( !isNumeric(strNum.substr(1).replace(/,/g, "")) )
		{
		  errMsg = "Please enter only digits";
			errorFlag = true;
		}
		else if ( parseFloat(strNum.substr(1).replace(/,/g, "")) < minNum || parseFloat(strNum.substr(1).replace(/,/g, "")) > maxNum )
		{
		  errMsg = "Specify a number from " + minNum.toString() + " to " + maxNum.toString();
		  errorFlag = true;
		}
		else
		{
		  var num = new NumberFormat(strNum);
	    num.setCurrency(true);
			num.setPlaces(2);
		}
	}
	else
	{
	  if ( !isNumeric(strNum.replace(/,/g, "")) )
		{
		  errMsg = "Number can only contain digits, decimal point and dollar sign";
			errorFlag = true;
		}
		else if ( parseFloat(strNum.replace(/,/g, "")) < minNum || parseFloat(strNum.replace(/,/g, "")) > maxNum )
		{
		  errMsg = "Specify a number from " + minNum.toString() + " to " + maxNum.toString();
		  errorFlag = true;
		}
		else
		{
		  var num = new NumberFormat(strNum);
	    num.setCurrency(true);
			num.setPlaces(2);
		}
	}
	
	if ( errorFlag )
	{
	  objTxtField.value = defaultNum;
		alert(errMsg);
		return false;
	}
	else
	{
	  objTxtField.value = num.toFormatted();
	  return true;
	}
}

function formatAsPercent(objTxtField, minNum, maxNum, defaultNum)
{	
  var errorFlag = false;
	var errMsg = "";
  var strNum = new String(objTxtField.value);
	
  // If a percent sign already exists at the end and the string has a length of at least 2
	// then see if everything up to the percent sign is a number. If it is then there's nothing
	// to do, return success
	if ( strNum.length == 0 )
	{
	  objTxtField.value = defaultNum;
	  return;
	}
	
	if ( strNum.indexOf("%") == strNum.length - 1 && strNum.length >= 2 )
	{
	  if ( !isNumeric(strNum.substr(0, strNum.length - 2)) )
		{
		  errMsg = "Please enter only digits";
			errorFlag = true;
		}
		else if ( parseFloat(strNum.substr(0, strNum.length - 2)) < minNum || parseFloat(strNum.substr(0, strNum.length - 2)) > maxNum )
		{
		  errMsg = "Specify a number from " + minNum.toString() + " to " + maxNum.toString();
		  errorFlag = true;
		}
	}
	else
	{
	  if ( !isNumeric(strNum) )
		{
		  errMsg = "Number can only contain digits, decimal point and percent sign";
			errorFlag = true;
		}
		else if ( parseFloat(strNum) < minNum || parseFloat(strNum) > maxNum )
		{
		  errMsg = "Specify a number from " + minNum.toString() + " to " + maxNum.toString();
		  errorFlag = true;
		}
/*	
    else if ( strNum.length == 0 )
		{
		  strNum += "0%";
		}
*/
		else
		{
		  strNum += "%";
		}
	}
	
	if ( errorFlag )
	{
	  objTxtField.value = defaultNum;
		alert(objTxtField.title + ": " + errMsg);
		return false;
	}
	else
	{
	  objTxtField.value = strNum;
	  return true;
	}
}

function formatAsInteger(objTxtField, minNum, maxNum, defaultNum, ignoreEmpty)
{	
  var errorFlag = false;
	var errMsg = "";
  var strNum = new String(objTxtField.value);
	
	// Verify field contents is not empty
	// Verify field contains digits only
	// Verify number is within limits
	// If any of these are false, set to defaultNum
  if ( strNum.length == 0 )
	{
	  objTxtField.value = defaultNum;
	  return;
	}
	
	if ( !isInteger(strNum) )
	{
	  errMsg = "Please enter only digits";
		errorFlag = true;
	}
	else if ( parseInt(strNum) < minNum || parseInt(strNum) > maxNum )
	{
	  errMsg = "Specify a number from " + minNum.toString() + " to " + maxNum.toString();
	  errorFlag = true;
	}
	
	if ( errorFlag )
	{
	  objTxtField.value = defaultNum;
		alert(errMsg);
		return false;
	}
	else
	{
	  objTxtField.value = strNum;
	  return true;
	}
}

function addDays(myDate, days)
{
  // myDate = a Date object
  // days = +/- days from date
  
  d = new Date(myDate.getTime() + days * 24 * 60 * 60 * 1000);
  
	// Under FireFox, getYear() returns 106 for 2006 for instance, so add 1900
	var year;
	if ( d.getYear() < 1900 )
	  year = d.getYear() + 1900;
	else
	  year = d.getYear();
		
  return (d.getMonth()+1) + "/" + d.getDate() + "/" + year;
}

function goPage(src)
{
  window.location.href = src;
}

function trim(s)
{
  while (s.substring(0,1) == ' ')
    s = s.substring(1,s.length);

  while (s.substring(s.length-1,s.length) == ' ')
    s = s.substring(0,s.length-1);

  return s;
}

function isUrl(s)
{
	var regexp = /(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/
	return regexp.test(s);
}


function isValidEmail(str)
{
  var re = /^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/;
  
	if ( !str.match(re) )
    return false;
	else
    return true;
}

function validateZip(field)
{
  var valid = "0123456789-";
  var hyphencount = 0;

  if (field.length!=5 && field.length!=10)
  {
    //alert("Please enter your 5 digit or 5 digit+4 zip code.");
    return false;
  }
  
  for (var i=0; i < field.length; i++)
  {
    temp = "" + field.substring(i, i+1);
    if (temp == "-")
	  hyphencount++;
    
	if (valid.indexOf(temp) == "-1")
	{
      //alert("Invalid characters in your zip code.  Please try again.");
      return false;
    }

    if ((hyphencount > 1) || ((field.length==10) && ""+field.charAt(5)!="-"))
	{
      //alert("The hyphen character should be used with a properly formatted 5 digit+four zip code, like '12345-6789'.   Please try again.");
      return false;
    }
  }
  return true;
}

function validatePhone(field)
{
	// Regex pattern for verifying a Canadian postal code
	var regex = /[0-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/
	
	if ( field.value.search(regex) == -1 )
	  return false;
	else
	  return true;
}

function isInteger(s)
{
  var i
  for (i = 0; i < s.length; i++)
  {   
    // Check that current character is number.
    var c = s.charAt(i)
    if ( (c < "0") || (c > "9") )
      return false
  }
  
  // All characters are numbers.
  return true
}

function clearDefault(strDefault, objField)
{
  if ( objField.value == strDefault )
    objField.value = '';
}

function deleteRecord(strURL)
{
	if ( confirm('Are you sure you want to delete this?') )
	  window.location.href = strURL;

  return;
}

// strField = name of column in table to sort by
// objSortBy = hidden input field used by function to store the sort by field name
// objSortDirection = hidden input field used by function to stor the sort direction
function sortBy(strField, objSortBy, objSortDirection)
{
	objSortBy.value = strField;
	
	if ( objSortDirection.value == "ASC" )
	  objSortDirection.value = "DESC";
	else
	  objSortDirection.value = "ASC";
	
}

function checkContactForm(objForm, maxMsgLen)
{
  var strErr = "";
	var strMsg = "Please correct the following:\n";
	
	if ( trim(objForm.name.value).length == 0 )
	  strErr += "- Name\n";
		
	if ( trim(objForm.email.value).length == 0 )
	  strErr += "- Email address\n";
	else if ( !isValidEmail(objForm.email.value) )
    strErr += "- Email address is not valid\n";
	
	if ( trim(objForm.phone.value).length == 0 )
	  strErr += "- Phone #\n";
		
	if ( trim(objForm.message.value).length == 0 )
	  strErr += "- Message\n";
	else if ( objForm.message.value.length > maxMsgLen )
    strErr += "- Message cannot exceed " + maxMsgLen + " characters in length\n";
	
	if ( strErr )
	{
	  alert(strMsg + strErr);
		return false;
	}
	else
	{
		objForm.submit();
		return true;
	}
}

function checkUnsubscribeForm(objForm)
{
  var strErr = "";
	var strMsg = "Please correct the following:\n";
	
	if ( trim(objForm.email.value).length == 0 )
	  strErr += "- Email address\n";
	else if ( !isValidEmail(objForm.email.value) )
    strErr += "- Email address is not valid\n";

	if ( strErr )
	{
	  alert(strMsg + strErr);
		return false;
	}
	else
	{
		objForm.submit();
		return true;
	}
}
