﻿//----------------------------------------------------------------------
// T O D L I B . J S
// Copyright (c) 2001-2003 Tom Ogden
// CREATED: 2001-09-21
// DESCRIPTION: Library of JavaScript functions for web sites. 
// SECTIONS: 
//      UTILITY FUNCTIONS
//      FILTERING & VALIDATION FUNCTIONS
//      COOKIE FUNCTIONS
//      SHOPPING CART FUNCTIONS
//      OBSOLETE FUNCTIONS
// 2003-06-12: Organized and formatted.
//----------------------------------------------------------------------
// AJAX FUNCTIONS
//----------------------------------------------------------------------
// FUNCTION: runRequest
// INPUT: src, task
// OUTPUT: revise and alert
// DESCRIPTION: Replace the text object with data from the URL. 
// CREATED: 2008-06-23
//----------------------------------------------------------------------
function runRequest ( src, id ) { 
	var XMLHttpRequestObject = false;

	if ( window.XMLHttpRequest ) {
		XMLHttpRequestObject = new XMLHttpRequest ( );
	} else if ( window.ActiveXObject ) {
		XMLHttpRequestObject = new ActiveXObject ( "Microsoft.XMLHTTP" );
	}
		
	if ( XMLHttpRequestObject ) {
		XMLHttpRequestObject.open ( "GET", src );
		
		XMLHttpRequestObject.onreadystatechange = function ( ) {
			if ( XMLHttpRequestObject.readyState == 4 
				&& XMLHttpRequestObject.status == 200 
			) {
				var myblock = document.getElementById ( id );	
					myblock.innerText = XMLHttpRequestObject.responseText;
			}
		}
		XMLHttpRequestObject.send ( null );
	}
}

//----------------------------------------------------------------------
// FUNCTION: href2block
// INPUT: href, blockID
// OUTPUT: 
// DESCRIPTION: Load data from href into an ID block object. 
// CREATED: 2008-12-18
//----------------------------------------------------------------------
function href2block ( href, blockID ) { 
	var XMLHttpRequestObject = false;

	if ( window.XMLHttpRequest ) {
		XMLHttpRequestObject = new XMLHttpRequest ( );
	} else if ( window.ActiveXObject ) {
		XMLHttpRequestObject = new ActiveXObject ( "Microsoft.XMLHTTP" );
	}
		
	if ( XMLHttpRequestObject ) {
		XMLHttpRequestObject.open ( "GET", href );
		
		XMLHttpRequestObject.onreadystatechange = function ( ) {
			if ( XMLHttpRequestObject.readyState == 4 
				&& XMLHttpRequestObject.status == 200 
			) {
				var myblock = document.getElementById ( blockID );	
					myblock.innerHTML = XMLHttpRequestObject.responseText;
			}
		}
		XMLHttpRequestObject.send ( null );
	}	
}

//----------------------------------------------------------------------
// FUNCTION: setModalBlock
// INPUT: href, blockID
// OUTPUT: 
// DESCRIPTION: Load data from href into an ID block object. 
// CREATED: 2008-12-18
//----------------------------------------------------------------------
function setModalBlock ( href ) { 
	// Load the block. 
	var blockID = "mBlock";
	href2block ( href, blockID )

	// Expose the mask.
	var mask = document.getElementById ( "mask" );
	mask.style.height = window.innerHeight;	
	mask.style.visibility = "visible";

	// Expose the modal block, centered horizontally. 
	var block = document.getElementById ( blockID );	
	var bwidth = 400; //arbitrary until we can calculate block width. 
	var leftpos = ( window.innerWidth - bwidth ) / 2; 
	if ( leftpos < 0 ) leftpos = 0; 
	block.style.left = leftpos;
	block.style.visibility = "visible";
}

//----------------------------------------------------------------------
// FUNCTION: closeModalBlock
// INPUT: href, blockID
// OUTPUT: 
// DESCRIPTION: Close the open ID block object. 
// CREATED: 2008-12-18
//----------------------------------------------------------------------
function closeModalBlock ( blockID ) { 
	// Load the block. 
	// href2block ( href, blockID )

	// Hide the modal block.
	var block = document.getElementById ( blockID );	
	block.style.visibility = "hidden";

	// Hide the mask.
	var mask = document.getElementById ( "mask" );	
	mask.style.visibility = "hidden";
}

//----------------------------------------------------------------------
// FUNCTION: keyPressHandler
// INPUT: event
// OUTPUT: 
// DESCRIPTION: Handle the key that is pressed. 
// CREATED: 2008-12-18
//----------------------------------------------------------------------
 function keyPressHandler ( event ) {
      var escOrd = 27;
      if ( event.keyCode == escOrd )
         closeModalBlock ( "mBlock" );
   }
 
//----------------------------------------------------------------------
// FUNCTION: ajax_updateValue
// INPUT: textID, o, id, entry, v
// OUTPUT: alert
// DESCRIPTION: Change VALUE of an entry. Intervene with confirmation 
// before calling do_method.php.
// CREATED: 2008-06-23
//----------------------------------------------------------------------
function ajax_updateValue ( textID, o, id, entry, arg ) { 		
	var now = new Date ( );
	if ( arg == "now" ) arg = now.toLocaleTimeString ( );
	var q = "Update field '" + entry + "' to '" + arg + "'?";
	if ( newarg = prompt ( q, arg ) ) {
		var phpScript  = "/bin/ajax/do_entry.php";
			phpScript += "?o=" + o;
			phpScript += "&id=" + id;
			phpScript += "&e=" + entry;
			phpScript += "&arg=" + newarg;
			
		runRequest ( phpScript, textID );
	}	
}

//----------------------------------------------------------------------
// FUNCTION: ajax_updateBoolean
// INPUT: textID, o, id, entry, v
// OUTPUT: alert
// DESCRIPTION: Change VALUE of an entry. Intervene with confirmation 
// before calling do_method.php.
// CREATED: 2008-06-23
//----------------------------------------------------------------------
function ajax_updateBoolean ( textID, o, id, entry, arg ) { 		
	var now = new Date ( );
	var newarg = 0;
	if ( arg == 0 ) {
		newarg = 1; 
	}
		
	var phpScript  = "/bin/ajax/do_entry.php";
		phpScript += "?o=" + o;
		phpScript += "&id=" + id;
		phpScript += "&e=" + entry;
		phpScript += "&arg=" + newarg;
		
	runRequest ( phpScript, textID );
}

//----------------------------------------------------------------------
// FUNCTION: valueUpdate
// INPUT: textID, o, id, m, arg
// OUTPUT: revise and alert
// DESCRIPTION: Run the method to replace the text. 
// CREATED: 2008-03-04
//----------------------------------------------------------------------
function valueUpdate ( textID, o, id, m, arg ) { 
	if ( XMLHttpRequestObject ) {
	var phpScript  = "/bin/ajax/do_method.php";
		phpScript += "?o=" + o;
		phpScript += "&id=" + id;
		phpScript += "&m=" + m;
		phpScript += "&arg=" + arg;
		XMLHttpRequestObject.open ( "GET", phpScript );
		XMLHttpRequestObject.onreadystatechange = function ( ) {
			if ( XMLHttpRequestObject.readState == 4 
				&& XMLHttpRequestObject.status == 200 
			) {
				chtxtID ( txtID, XMLHttpRequestObject.responseText );
			}
		}
		XMLHttpRequestObject.send ( null );
	}
}

//----------------------------------------------------------------------
// FUNCTION: filterDistinct
// INPUT: field, table
// OUTPUT: revise and alert
// DESCRIPTION: Call script query for match, empty value if match found. 
// CREATED: 2008-01-15
//----------------------------------------------------------------------
function filterDistinct ( input, table ) { 
	if ( myInput.value.length > 0 ) {
		if ( XMLHttpRequestObject ) {
		var phpScript  = "/bin/ajax/do_distinct.php";
			phpScript += "?field=" + input.name + "&table=" + table;
			phpScript += "&value=" + input.value;
			XMLHttpRequestObject.open ( "GET", phpScript );
			XMLHttpRequestObject.onreadystatechange = function ( ) {
				if ( XMLHttpRequestObject.readState == 4 
					&& XMLHttpRequestObject.status == 200 
				) {
					if ( XMLHttpRequestObject.responseText > 0 ) {
						alert ( "Field value '" + input.value + "' is already taken." );
						input.value = "";
						input.select ( );
						return ( false );
					} else {
						return( true );
					}
				}
			}
			XMLHttpRequestObject.send ( null );
		}
	} else {
		 return( true );
	}
}

//----------------------------------------------------------------------
// FUNCTION: chpicID
// INPUT: imgID, filename
// OUTPUT: 
// DESCRIPTION: Load new picture into <img> object from picture library. 
// CREATED: 2007-12-04
//----------------------------------------------------------------------
function chpicID ( imgID, newfilename ) {
	var img = document.getElementById ( imgID );

	var partsArray = img.src.split ( "/" );
	var filename = partsArray.pop ( );
	
		partsArray.push ( newfilename );
	
		img.src = partsArray.join ( "/" );
}

//----------------------------------------------------------------------
// FUNCTION: chtxtID
// INPUT: txtID, newtxt
// OUTPUT: 
// DESCRIPTION: Load new string text into an ID text object. 
// CREATED: 2008-01-14
//----------------------------------------------------------------------
function chtxtID ( txtID, newtxt ) {
	var myblock = document.getElementById ( txtID );	
		myblock.innerText = newtxt;
}

//----------------------------------------------------------------------
// FUNCTION: chblockID
// INPUT: newData, blockID
// OUTPUT: 
// DESCRIPTION: Load new string data into an ID block object. 
// CREATED: 2008-12-18
//----------------------------------------------------------------------
function chblockID ( newData, blockID ) {
	alert ( "Entering function..." );
	var myblock = document.getElementById ( blockID );	
		myblock.innerHTML = newData;
}

//----------------------------------------------------------------------
// UTILITY FUNCTIONS
//----------------------------------------------------------------------
// FUNCTION: test
// INPUT: 
// OUTPUT: alert string
// DESCRIPTION: Test this library for globally crippling syntax errors.
// CREATED: 
//----------------------------------------------------------------------
function test () {
	alert("Library toDlib is active.");
}

//----------------------------------------------------------------------
// FUNCTION: isEmpty
// INPUT: inputStr
// OUTPUT: true or false
// DESCRIPTION: Test value for empty string or null.
// CREATED: 2003-07-07
//----------------------------------------------------------------------
function isEmpty ( inputStr ) {
	if ( inputStr == null || inputStr == "" ) {
		return ( true );
	}
	return ( false );
}

//----------------------------------------------------------------------
// FUNCTION: setImage
// INPUT: myImage, newImage
// OUTPUT: changes image
// DESCRIPTION: Create a rollover.
// CREATED: 
//----------------------------------------------------------------------
function setImage(myImage,newImage) {
	myImage.src = newImage.src;
}

//----------------------------------------------------------------------
// FUNCTION: sequenceImages
// INPUT: imageArray, imageIndex, imageName (all globals)
// OUTPUT: changes images
// DESCRIPTION: Used by 'rotateImages' to change images using global 
// variables of conventional names. Go through 'setImage'.
// CREATED: 2004-01-28
//----------------------------------------------------------------------
function sequenceImages ( ) {
	setImage ( document.imageName, imageArray[imageIndex] );
	imageIndex++;
	if ( imageIndex >= imageArray.length ) imageIndex = 0;
}

//----------------------------------------------------------------------
// FUNCTION: rotateImages
// INPUT: delay
// OUTPUT: Sets an Interval to change images
// DESCRIPTION: Rotate an array of images through an IMG tag. 
// CREATED: 2004-01-27
//----------------------------------------------------------------------
function rotateImages ( delay ) {
	var intervalID = setInterval ( "sequenceImages ( )", delay );
}

// DEPROCATE 2008-01-27: imageCollection variable is not found and causes
// error, which is repeated in an infinite loop. 
//----------------------------------------------------------------------
// FUNCTION: sequenceImagesRand
// INPUT: imageArray, imageIndex, imageName (all globals)
// OUTPUT: changes images
// DESCRIPTION: Rotate images on random sets of pictures, with given interval.
// CREATED: 2005-10-26
//----------------------------------------------------------------------
// function sequenceImagesRand ( ) {
// 	var arrayIndex = Math.floor ( Math.random ( ) * ( imageCollection.length + 1 ) );
// 	var imgIndex = imageIndex[arrayIndex];
// 		
// 	setImage ( document.images["imageName"+arrayIndex], imageCollection[arrayIndex][imgIndex] );
// 	imgIndex++;
// 	if ( imgIndex >= imageCollection[arrayIndex].length ) imgIndex = 0;
// 	imageIndex[arrayIndex] = imgIndex;
// }


// DEPROCATE 2008-01-27: Calls sequenceimagesRand which causes
// error, which is repeated in an infinite loop. 
//----------------------------------------------------------------------
// FUNCTION: rotateImagesRand
// INPUT: delay
// OUTPUT: Sets an Interval to change images
// DESCRIPTION: Call randomSequenceImages to randomly select arrays 
// of images to rotate
// CREATED: 2005-10-25
//----------------------------------------------------------------------
// function rotateImagesRand ( delay ) {
// 	delay = Math.floor ( Math.random ( ) * delay ) + 1;
// 	var intervalID = setInterval ( "sequenceImagesRand ( )", delay );
// }

//----------------------------------------------------------------------
// FUNCTION: str2hex
// INPUT: myStr
// OUTPUT: hexStr
// DESCRIPTION: Encrypt any text string to a collection of hex codes.
// CREATED: 2003-06-11
// 2007-08-10: Force numbers to string type. 
//----------------------------------------------------------------------
function str2hex ( myStr ) {
	var hexStr = "";
	var thisCharCode = "";
	myStr = "" + myStr; // Ensure numbers are converted to string type
	for ( i = 0; i < myStr.length; i++ ) {
		thisCharCode = myStr.charCodeAt ( i );
		hexStr += thisCharCode.toString ( 16 );	
	}
	
	return hexStr.toUpperCase ( );
}

//----------------------------------------------------------------------
// FUNCTION: hex2str
// INPUT: myHex
// OUTPUT: newStr
// DESCRIPTION: Decrypt a block of hex codes to the original string.
// CREATED: 2003-06-11
// 2008-12-01: Change variable 'i' to 'hexi' to prevent affecting enclosing functions. 
//----------------------------------------------------------------------
function hex2str ( myHex ) {
	var newStr = "";
	var hexChar = "";
	var charCode;
	var isEven = false;
	for ( hexi = 0; hexi < myHex.length; hexi++ ) {
		if ( isEven ) {
			isEven = false;
			hexChar += myHex.charAt ( hexi );
			charCode = parseInt ( hexChar, 16 );
			newStr += String.fromCharCode ( charCode );
		} else {
			isEven = true;
			hexChar = myHex.charAt ( hexi );
		}
	}
	
	return newStr;
}

//----------------------------------------------------------------------
// FUNCTION: strContains
// INPUT: str, substr
// OUTPUT: boolean
// DESCRIPTION: Determine if substring is contained in string.
// Always case-sensitive turned on. 
// CREATED: 2008-11-29 from PHP function of same name. 
//----------------------------------------------------------------------
function strContains ( str, substr ) {
	var result = str.indexOf ( substr, 0 );
	
	// Not found is -1. Found is position, which COULD be zero. 
	if ( result > -1 ) {
		return ( true );
	} else {
		return ( false );
	}
}
	
//----------------------------------------------------------------------
// FUNCTION: listPlugins
// INPUT: 
// OUTPUT: 
// DESCRIPTION: List all plugins installed in this browser. 
// DOES NOT WORK IN IE. 
// CREATED: 2008-11-29
//----------------------------------------------------------------------
function listPlugins ( ) {
	if (navigator.plugins != null && navigator.plugins.length > 0) { 
		for ( var i = 0; i < navigator.plugins.length; i++ ) {
			document.write ( i + ": " + navigator.plugins[i].name + "<br />" );
		}
	} else {
		document.write ( "No navigator plugins found.<br />" );
	}
	
	return ( i );
}

//----------------------------------------------------------------------
// FUNCTION: hasPlugin
// INPUT: name
// OUTPUT: boolean
// DESCRIPTION: Check browser arrays for a given plugin.
// DOES NOT WORK IN IE. 
// CREATED: 2008-11-29
//----------------------------------------------------------------------
function hasPlugin ( name ) {
	if (navigator.plugins != null && navigator.plugins.length > 0) { 
		for ( var i = 0; i < navigator.plugins.length; i++ ) {
			if ( strContains ( navigator.plugins[i].name, name ) ) {
				return ( true );
			}
		}
	}
	
	return ( false );
}

//----------------------------------------------------------------------
// FUNCTION: hasPluginIE
// INPUT: name
// OUTPUT: boolean
// DESCRIPTION: Check IE for an exact plugin. Name must be completely accurate. 
// Made especially for IE. 
// CREATED: 2008-11-29
//----------------------------------------------------------------------
function hasPluginIE ( name ) {
	var version;
	var axo;
	var e;

	try {
		axo = new ActiveXObject ( name );
		version = axo.GetVariable ( "$version" );
	} catch ( e ) {
	}

	if ( version ) {
		return ( true );
	} else {
		return ( false );
	}
}

//----------------------------------------------------------------------
// FUNCTION: compare
// INPUT: v0, v1
// OUTPUT: result
// DESCRIPTION: Compare 2 values and return integer for a sorting array. 
// CREATED: 2005-01-11
//----------------------------------------------------------------------
function compare ( v0, v1 ) {
	if ( v0 == v1 ) return ( 0 );
	if ( v0 > v1 ) return ( 1 );
	if ( v0 < v1 ) return ( -1 );
}

//----------------------------------------------------------------------
// FUNCTION: delImage
// INPUT: src, object, name
// OUTPUT: alert
// DESCRIPTION: Obtain approval, then forward to record delete script.
// CREATED: 2002-10-20
//----------------------------------------------------------------------
function delImage ( dirPath, object, name ) { 
	var q  = "Are you sure you want to permanently \r";
		q += "delete the image for " + object + " \r";
		q += "'" + name + "'?";
			
	if ( confirm ( q ) ) {
		setMarker ( "p" );
		var newLoc = "do_del.php?o=image&d=" + dirPath;
		window.location = newLoc;
	}
}

//----------------------------------------------------------------------
// FUNCTION: delRecord
// INPUT: object, id, name
// OUTPUT: alert
// DESCRIPTION: Obtain approval, then forward to record delete script.
// CREATED: 2002-10-20
//----------------------------------------------------------------------
function delRecord ( object, id, name ) { 
	var q = "Are you sure you want to permanently delete " + object + " '" + name + "'?";
			
	if ( confirm ( q ) ) {
		setMarker ( "" );
		var newLoc = "do_del.php?id=" + id + "&o=" + object;
		window.location = newLoc;
	}
}

//----------------------------------------------------------------------
// FUNCTION: canRecord
// INPUT: object, id, name
// OUTPUT: alert
// DESCRIPTION: Change status to zero/false and back, depending on current status.
// CREATED: 2003-06-24
//----------------------------------------------------------------------
function canRecord ( object, id ) { 		
	//-- var q = "Are you sure you want to change the status of this " + object + "?";
	//--if ( confirm ( q ) ) {
		var newLoc = "do_can.php?id=" + id + "&o=" + object;
		setMarker ( "" );
		window.location = newLoc;
	//--}
}

//----------------------------------------------------------------------
// FUNCTION: confirmChanges
// INPUT: URI, alertStr
// OUTPUT: 
// DESCRIPTION: Send changes to do_execute, but ask for approval first.
// CREATED: 2005-06-30
//----------------------------------------------------------------------
function confirmChanges ( URI, alertStr ) { 
	var approval = false;	
	if ( URI.length ) {
		approval = confirm ( alertStr );
	} else {
		approval = true;	
	}
	
	if ( approval ) {
		var newLoc = "do_execute.php" + URI;
		setMarker ( "" );
		window.location = newLoc;
	} else {
		window.history[0];
	}
}

//----------------------------------------------------------------------
// FUNCTION: updateField
// INPUT: o, id, entry, v
// OUTPUT: alert
// DESCRIPTION: Change contents of a field. Intervene with confirmation 
// before calling do_updateField.php.
// CREATED: 2005-04-12
// 2005-10-17: Change from 'confirm' to 'promp' to enable user ammendment.
//----------------------------------------------------------------------
function updateField ( o, id, entry, v ) { 		
	var now = new Date ( );
	if ( v == "now" ) v = now.toLocaleTimeString ( );
	var q = "Update field '" + entry + "' to '" + v + "'?";
	if ( answ = prompt ( q, v ) ) {
		var newLoc = "do_updateField.php?";
		newLoc += "o=" + o;
		newLoc += "&id=" + id;
		newLoc += "&entry=" + entry;
		newLoc += "&value=" + answ;
		setMarker ( "" );
		window.location.href = newLoc;
	}
}

//----------------------------------------------------------------------
// FUNCTION: submitChild
// INPUT: myForm
// OUTPUT: 
// DESCRIPTION: Pack form data into a valuePod string and insert into 
// parentEntry's form field.
// CREATED: 2006-11-07
//----------------------------------------------------------------------
function submitChild ( myForm, parentEntry, id ) {
	var serialArray = new Array ( );
	for ( j = 0; j < myForm.elements.length; j++ ) {
		serialArray[j] = str2hex ( myForm.elements[j].name );
		serialArray[j] += ":" + str2hex ( myForm.elements[j].value );
	}
	var vPod = id + ";" + serialArray.join ( ";" );
	window.close();
	opener.focus();
	var parentForm = opener.document.forms[0];
	parentForm.elements[parentEntry].value = vPod;
	parentForm.action = opener.location.href;
	parentForm.submit ( );
}

//----------------------------------------------------------------------
// FUNCTION: prependField
// INPUT: o, id, entry, v
// OUTPUT: alert
// DESCRIPTION: Push a string into the front of a field. Intervene with 
// confirmation before calling do_prependField.php.
// CREATED: 2006-09-23
//----------------------------------------------------------------------
function prependField ( o, id, entry, v ) { 		
	var now = new Date ( );
	if ( v == "now" ) v = now.toLocaleTimeString ( );
	var q = "Update field '" + entry + "' to '" + v + "'?";
	if ( answ = prompt ( q, v ) ) {
		var newLoc = "do_prependField.php?";
		newLoc += "o=" + o;
		newLoc += "&id=" + id;
		newLoc += "&entry=" + entry;
		newLoc += "&value=" + answ;
		setMarker ( "" );
		window.location = newLoc;
	}
}

//----------------------------------------------------------------------
// FUNCTION: reSearch
// INPUT: argArrayStr
// OUTPUT: location.search
// DESCRIPTION: Revisit the current page while updating the search string.
// CREATED: 2003-07-10
//----------------------------------------------------------------------
function reSearch ( argArrayStr ) { 		
	var searchStr = "";
	var argArray = argArrayStr.split ( ";" );
	for ( i = 0; i < argArray.length; i++ ) {
		var myArg = argArray[i].split ( "," );
		if ( i == 0 ) {
			searchStr += "?";
		} else {
			searchStr += "&";
		}
		searchStr += myArg[0] + "=" + myArg[1];
	}
	
	window.location.search = searchStr;
}

//----------------------------------------------------------------------
// FUNCTION: this2value
// INPUT: myControl, otherControl
// OUTPUT: 
// DESCRIPTION: Translate the checked state of a checkbox to the value of
// another control, using the value of the checkbox; also set value to value.
// CREATED: 2003-08-02
// 2003-09-23: Broadened to other controls, file input in particular.
//----------------------------------------------------------------------
function this2value ( myControl, otherControl ) { 
	if ( myControl.type == "checkbox" ) {
		if ( myControl.checked ) {
			otherControl.value = myControl.value;
		} else {
			if ( myControl.value == "1" ) {
				otherControl.value = 0;
			} else {
				otherControl.value = "";
			}
		}
	} else {
		otherControl.value = myControl.value;
	}	
}

//----------------------------------------------------------------------
// FUNCTION: this2IDvalue
// INPUT: myControl, otherControlID
// OUTPUT: 
// DESCRIPTION: Translate the checked state of a checkbox to the value of
// another control, using the value of the checkbox; also set value to value.
// Adapted from this2value, but uses AJAX ID call. 
// CREATED: 2007-12-05
//----------------------------------------------------------------------
function this2IDvalue ( myControl, otherControlID ) { 
	var otherControl = document.getElementById ( otherControlID );
	if ( myControl.type == "checkbox" ) {
		if ( myControl.checked ) {
			otherControl.value = myControl.value;
		} else {
			if ( myControl.value == "1" ) {
				otherControl.value = 0;
			} else {
				otherControl.value = "";
			}
		}
	} else {
		otherControl.value = myControl.value;
	}	
}

//----------------------------------------------------------------------
// FUNCTION: checklist2IDvalue
// INPUT: myControl, otherControlID
// OUTPUT: 
// DESCRIPTION: Translate the checked state of a checkbox to the value of
// another control, using the value of the checkbox; also set value to value.
// Adapted from this2value, but uses AJAX ID call. 
// CREATED: 2007-12-05
//----------------------------------------------------------------------
function checklist2IDvalue ( seriesName, seriesCount, otherControlID ) { 
	var newValArray = new Array ( );
	
	// Walk thru controls and collect values
	for ( i = 0; i < seriesCount; i++ ) {	
		var myControl = document.getElementById ( seriesName + "_" + i );
		if ( myControl.type == "checkbox" ) {
			if ( myControl.checked ) {
				newValArray.push ( myControl.value );
			}
		}
	}

	// Merge values into a string
	var otherControl = document.getElementById ( otherControlID );
	otherControl.value = newValArray.join ( "," );
}

//----------------------------------------------------------------------
// FILTERING & VALIDATION FUNCTIONS
//----------------------------------------------------------------------
// FUNCTION: parseOutAlpha
// INPUT: myStr
// OUTPUT: newValue
// DESCRIPTION: Remove all alpha chars from number. Allow one decimal.
// CREATED: 2003-06-06
//----------------------------------------------------------------------
function parseOutAlpha ( myStr ) {
	var strlen = myStr.length + 3;
	var charNum = 0;
	var newStr = "";
	var FOUNDdot = false;
	for ( var i = 0; !isNaN ( charNum = myStr.charCodeAt ( i ) ); i++ ) {
		if ( charNum >= 48 && charNum <= 57  ) {
			newStr += String.fromCharCode ( charNum );
		} else if ( charNum == 46 && !FOUNDdot ) {
			FOUNDdot = true;
			newStr += String.fromCharCode ( charNum );
		}
	}
	newValue = parseFloat ( newStr );
	return newValue;
}

//----------------------------------------------------------------------
// FUNCTION: softSubmit
// INPUT: myForm, myAction
// OUTPUT: 
// DESCRIPTION: Submit form to alternate action, cancel checkForm.
// Action may resubmit to same form or to alternate check script.
// CREATED: 2003-07-11
//----------------------------------------------------------------------
function softSubmit ( myForm, myAction ) {
	myForm.action = myAction + "?s=0";
	myForm.onSubmit  = "";
	myForm.submit ( );
}

//----------------------------------------------------------------------
// FUNCTION: filterInt
// INPUT: myInput, min, max
// OUTPUT: revise and alert
// DESCRIPTION: Gives alert if value is out of range and corrects it.
// CREATED: 2003-06-06
//----------------------------------------------------------------------
function filterInt ( myInput, min, max, label ) { 
	var newValue = parseInt ( parseOutAlpha ( myInput.value ) );
	if ( isNaN ( newValue ) ) newValue = 0;

	if ( newValue < min ) {
		myInput.value = min;
		alert ( label + " must be at least " + min + "." );
		myInput.select ( );
	} else if ( newValue > max ) {
		myInput.value = max;
		alert ( "Sorry, but " + newValue + " is too high.\n" + label + " cannot be greater than " + max + "." );
		myInput.select ( );
	} else {
		myInput.value = newValue;
	}
}

//----------------------------------------------------------------------
// FUNCTION: filterUBI
// INPUT: myInput
// OUTPUT: revise and alert
// DESCRIPTION: Gives alert if value is not a legal UBI and removes it.
// CREATED: 2005-03-26
//----------------------------------------------------------------------
function filterUBI ( myInput ) { 
	var myStr = myInput.value;
	var strlen = myStr.length;
	var charNum = 0;
	var newStr = "";
	for ( var i = 0; !isNaN ( charNum = myStr.charCodeAt ( i ) ); i++ ) {
		if ( charNum >= 48 && charNum <= 57  ) {
			newStr += String.fromCharCode ( charNum );
		}
	}
	if ( !isNaN ( newStr ) ) {
		if ( newStr.length == 9 ) {
			myInput.value = newStr.substr ( 0, 3 ) + " " + newStr.substr ( 3, 3 ) + " " + newStr.substr ( 6, 3 );
			return;
		}
	}

	alert ( "Sorry, but '" + myStr + "' was not a valid entry.\n UBI must have 9 digits and no letters." );
	myInput.value = "";
	myInput.select ( );
}

//----------------------------------------------------------------------
// FUNCTION: filterUC
// INPUT: myInput
// OUTPUT: ( changed string value )
// DESCRIPTION: Changes contents to upper case.
// CREATED: 2003-07-24
//----------------------------------------------------------------------
function filterUC ( myInput ) { 
	myInput.value = myInput.value.toUpperCase ( );
}

//----------------------------------------------------------------------
// FUNCTION: filterDate
// INPUT: myInput
// OUTPUT: ( changed string value, alert )
// DESCRIPTION: Adds slashes when missing and alerts the user. This is
// quite limited, as the intelligence needed can be great.
// CREATED: 2003-12-13
//----------------------------------------------------------------------
function filterDate ( myInput ) { 
	if ( myInput.value.length > 0 ) {
		var myStr = myInput.value;
		var newStr = "";
		var partsArray = myStr.split ( "/" );
		if ( partsArray.length == 1 ) {
			var partsArray = myStr.split ( "-" );
			if ( partsArray.length == 1 ) {
				if ( myStr.length == 6 ) {
					newStr  = myStr.substr ( 0, 2 ) + "/";
					newStr += myStr.substr ( 2, 2 ) + "/";
					newStr += myStr.substr ( 4, 2 );
					myInput.value = newStr;
					alert ( "The date you entered has been corrected. Please confirm that it is correct." );
				} else if ( myStr.length == 8 ) {
					newStr  = myStr.substr ( 0, 2 ) + "/";
					newStr += myStr.substr ( 2, 2 ) + "/";
					newStr += myStr.substr ( 4, 4 );
					myInput.value = newStr;
					alert ( "The date you entered has been corrected. Please confirm that it is correct." );
				} else if ( myStr.length < 8 ) {
					alert ( "The date you entered is not in a recognized format." );
				}
			}
		}
		return ( false );
	} else {
		return ( true );
	}	
}

//----------------------------------------------------------------------
// FUNCTION: filterEmail
// INPUT: myInput
// OUTPUT: revise and alert
// DESCRIPTION: Gives alert if value is not a valid address.
// CREATED: 2003-06-06
//----------------------------------------------------------------------
function filterEmail ( myInput ) { 
	if ( myInput.value.length > 0 ) {
		var myAddress = myInput.value.replace ( /</, "" );
		myAddress = myAddress.replace ( />/, "" );
		myAddress = myAddress.replace ( /\"/, "" );
		myAddress = myAddress.replace ( /\'/, "" );
		myAddress = myAddress.replace ( /\?/, "" );
		myAddress = myAddress.replace ( /&/, "" );
		myAddress = myAddress.replace ( / /, "" );
		myAddress = myAddress.replace ( /\t/, "" );
		myInput.value = myAddress;
		
		var partsArray = myAddress.split ( "@" );
		if ( partsArray.length == 2 ) {
			if ( partsArray[0].length > 0 ) {
				var part2 = partsArray[1];
				domainArray = part2.split ( "." );
				if ( domainArray.length == 2 ) {
					if ( domainArray[0].length > 0 ) {
						var tld = domainArray[1];
						if ( tld.length >= 2 && tld.length <= 4 ) {
							return ( true );
						}
					}
				}
			}
		}
		
		alert ( "E-mail address is not valid." );
		myInput.select ( );
		return ( false );
	} else {
		return ( true );
	}
}

//----------------------------------------------------------------------
// FUNCTION: filterCreditCard
// INPUT: myInput
// OUTPUT: revise and alert
// DESCRIPTION: Gives alert if value is not a valid address.
// CREATED: 2006-11-09
//----------------------------------------------------------------------
function filterCreditCard ( myInput ) { 
	if ( myInput.value.length > 0 ) {
		var ccnLength = 16;
		var newCCN = "";
		
		// CLEAN OUT NON-DIGITS
		var ccNumber = parseOutAlpha ( myInput.value ) + ""; // Add empty string to convert to string type.
		ccNumber = ccNumber.replace ( /\./, "" );
		if ( ccNumber.length > ccnLength ) 
			ccNumber = ccNumber.substr ( 0, ccnLength );

		// RE-INSERT SPACES FOR DISPLAY
		for ( k = 0; k < ccNumber.length; k++ ) {
			if ( ( k > 0 ) && ( k % 4 == 0 ) ) newCCN += " ";
			
			var chr = ccNumber.charAt ( k );
			newCCN += chr;
		}
		
		// FEED BACK INTO FIELD
		myInput.value = newCCN;
		
		// INSPECT AND RESPOND
		if ( ccNumber.length < ccnLength ) {
			alert ( "Credit card number is not valid." );
			myInput.select ( );
			return ( false );
		} else {
			return ( true );
		}
	} else {
		return ( true ); // empty, but not wrong
	}
}

//----------------------------------------------------------------------
// FUNCTION: nameFromPath
// INPUT: path
// OUTPUT: name
// DESCRIPTION: Parses a filepath for a filename using filterFilename, 
// then parses the filename for a name. 
// CREATED: 2006-10-12
//----------------------------------------------------------------------
function nameFromPath ( path ) { 
	var filename = filterFilename ( path );
	
	var partsArray = filename.split ( "." );	
	var name = partsArray.shift ( );
	return ( name );
}

//----------------------------------------------------------------------
// FUNCTION: filterFilename
// INPUT: path
// OUTPUT: filename
// DESCRIPTION: Parses a filepath for a filename, DOS & Unix formats.
// CREATED: 2005-10-19
//----------------------------------------------------------------------
function filterFilename ( path ) { 
	var partsArray = path.split ( "\\" );
	if ( partsArray.length == 1 ) 
		partsArray = path.split ( "/" );
	
	var filename = partsArray.pop ( );
	return ( filename );
}

//----------------------------------------------------------------------
// FUNCTION: chkGraphicFormat
// INPUT: path
// OUTPUT: filename
// DESCRIPTION: Looks at the file's extension to verify valid graphic format.
// CREATED: 2006-02-25
//----------------------------------------------------------------------
function chkGraphicFormat ( input ) { 
	var filename = filterFilename ( input.value );
	var partsArray = filename.split ( "." );
	if ( partsArray.length >= 2 ) {
		var extension = partsArray.pop ( );
		extension = extension.toUpperCase ( );
		switch ( extension ) {
			case "JPG":
				return ( true );
				break;
			case "JPEG":
				return ( true );
				break;
			case "GIF":
				return ( true );
				break;
			case "GIFF":
				return ( true );
				break;
			case "PNG":
				return ( true );
				break;
			default:
				alert ( "This file, with extension '." + extension + "', does not appear to be a valid graphic format.\r\rFiles should be of type .JPG, .GIF or .PNG." );
				break;
		}
	} else {
		alert ( "This file has not extension and does not appear to be a valid graphic format.\r\rFiles should be of type .JPG, .GIF or .PNG." );
	}
	
	input.value = "";
	return ( false );
}

//----------------------------------------------------------------------
// FUNCTION: checkForm
// INPUT: myInput, min, max
// OUTPUT: revise and alert
// DESCRIPTION: Gives alert if value is out of range and corrects it.
// CREATED: 2003-06-06
//----------------------------------------------------------------------
function checkForm ( myForm ) {
	var checkArray = myForm.checkArrayStr.value.split ( ";" );
	for ( i = 0; i < checkArray.length; i++ ) {
		var fieldArray = checkArray[i].split ( "," );
		var chkbxName = fieldArray[0] + "Chkbx";
		for ( j = 0; j < myForm.elements.length; j++ ) {
			if ( myForm.elements[j].name == fieldArray[0] ) {
				if ( isEmpty ( myForm.elements[j].value ) ) {
					alert ( "Please fill in the '" + fieldArray[1] + "' field." );
					myForm.elements[j].focus ( );
					return ( false );
				} else if ( 
					myForm.elements[j].value == 0 
					&& myForm.elements[chkbxName].type == "checkbox"
				) {
					alert ( "You must select the '" + fieldArray[1] + "' checkbox to submit." );
					myForm.elements[chkbxName].focus ( );
					return ( false );
				}
			}
		}
	}
return ( true );
}

//----------------------------------------------------------------------
// FUNCTION: enableForm
// INPUT: myForm
// OUTPUT: 
// DESCRIPTION: Enables all inputs within the form.
// CREATED: 2005-09-14
//----------------------------------------------------------------------
function enableForm ( myForm ) {
	for ( i = 0; i < myForm.elements.length; i++ ) {
		myForm.elements[i].disabled = false;
	}
}

//----------------------------------------------------------------------
// FUNCTION: enableAB
// INPUT: myForm, A, B
// OUTPUT: 
// DESCRIPTION: Enables inputs within the form with indexes from A to B.
// CREATED: 2007-03-24
//----------------------------------------------------------------------
function enableAB ( myForm, A, B ) {
	for ( i = A; i <= B; i++ ) {
		myForm.elements[i].disabled = false;
	}
}

//----------------------------------------------------------------------
// FUNCTION: wakePrompt
// INPUT: myForm
// OUTPUT: 
// DESCRIPTION: Enables specified input on condition of emptyness.
// CREATED: 2006-06-21
//----------------------------------------------------------------------
function wakePrompt ( myInput ) {
if(document.searchForm.searchText.disabled){document.searchForm.searchText.disabled=false;document.searchForm.searchText.value='';document.searchForm.searchText.focus();document.searchForm.searchText.select();}
	for ( i = 0; i < myForm.elements.length; i++ ) {
		myForm.elements[i].disabled = false;
	}
}

//----------------------------------------------------------------------
// COOKIE FUNCTIONS
//----------------------------------------------------------------------
// FUNCTION: setCookie
// INPUT: name, value, interval
// OUTPUT: cookie
// DESCRIPTION: Creates a cookie. Interval is seconds from now to expiration.
// CREATED: 2003-06-05, by Tom Ogden Design. All rights reserved.
//----------------------------------------------------------------------
function setCookie ( name, value, interval ) { 
	//-- interval must be in seconds. 
	interval = interval * 1000; //-- Change to milliseconds for setTime.
	var expiration = new Date ( );
	var timeInt = expiration.getTime ( ) + interval
	expiration.setTime ( timeInt );
	cookieStr = name + "=" + value; //-- Eliminate spaces in cookies.
	cookieStr += "; expires=";
	cookieStr += expiration.toGMTString ( );
	cookieStr += "; path=/";
	document.cookie = cookieStr;
}

//----------------------------------------------------------------------
// FUNCTION: copyCookie
// INPUT: name0, name1
// OUTPUT: cookie
// DESCRIPTION: Copy an existing cookie into another cookie by new name.
// CREATED: 2007-06-12, by Tom Ogden Design. All rights reserved.
//----------------------------------------------------------------------
function copyCookie ( name0, name1 ) { 
	//-- interval must be in seconds. 
	interval = 84600 * 1000; //-- Change to milliseconds for setTime.
	var expiration = new Date ( );
	var timeInt = expiration.getTime ( ) + interval
	expiration.setTime ( timeInt );
	
	//-- Value
	var value = getCookieData ( name0 );
	cookieStr = name1 + "=" + value; //-- Eliminate spaces in cookies.
	cookieStr += "; expires=";
	cookieStr += expiration.toGMTString ( );
	cookieStr += "; path=/";
	document.cookie = cookieStr;
}

//----------------------------------------------------------------------
// FUNCTION: cookie2entryArray
// INPUT: name
// OUTPUT: entryArray
// DESCRIPTION: Read a dataclass cookie and parse its fields into an array. 
// CREATED: 2008-12-01, by Tom Ogden. All rights reserved.
// No associative keys are allowed in JavaScript. 
//----------------------------------------------------------------------
function cookie2entryArray ( name ) { 
	var data = getCookieData ( name );
	var entryArray = [];
	var partsArray = data.split ( "." );
	var partsArray2 = partsArray[2].split ( "|" );

	for ( ic2e = 0; ic2e < partsArray2.length; ic2e++ ) {
		var entry = partsArray2[ic2e].split ( ":" );
		entry[0] = hex2str ( entry[0] );
		entry[1] = hex2str ( entry[1] );
		entryArray[ic2e] = entry;
	}
	
	return ( entryArray );
}

//----------------------------------------------------------------------
// FUNCTION: cookie2Form
// INPUT: cookie, myForm
// OUTPUT: 
// DESCRIPTION: Populate the values of a form with entryArray from cookie. 
// CREATED: 2008-12-02, by Tom Ogden. All rights reserved.
//----------------------------------------------------------------------
function entryArray2Form ( cookie, myForm ) { 
	entryArray = cookie2entryArray ( cookie );

	for ( mkey in entryArray ) {
		if (typeof myForm.elements[entryArray[mkey][0]] != 'undefined') {
			myForm.elements[entryArray[mkey][0]].value = entryArray[mkey][1];
		} else {
			//alert ( "No control exists named '" + entryArray[mkey][0] + "'." );
		}
	}
}

//----------------------------------------------------------------------
// FUNCTION: delCookie
// INPUT: name
// OUTPUT: 
// DESCRIPTION: Deletes the specified cookie.
// CREATED: 2003-07-24
// 2007-08-10: Make it actually work by using setCookie. 
//----------------------------------------------------------------------
function delCookie ( name ) { 
	setCookie ( name, "", 0 );
}

//----------------------------------------------------------------------
// FUNCTION: getCookieData
// INPUT: label
// OUTPUT: cookie's data field
// DESCRIPTION: Given cookie label, get it's data
// CREATED: 2002-10-21
//----------------------------------------------------------------------
function getCookieData ( label ) { 
	var labelLen = label.length;
	var cookieLen = document.cookie.length;
	var cookieEnd;

	for ( var i = 0; i < cookieLen; i++ ) {
		var j = i + labelLen;
		if ( document.cookie.substring ( i, j ) == label ) {
			cookieEnd = document.cookie.indexOf ( ";", j );
			if ( cookieEnd < 0 ) {
				cookieEnd = document.cookie.length;
			}
			return unescape ( document.cookie.substring ( j+1, cookieEnd ) );
		}
	}
	return false;
}

//----------------------------------------------------------------------
// FUNCTION: cookiesEnabled
// INPUT: 
// OUTPUT: true or false if enabled
// DESCRIPTION: Test for browser enabled cookies by creating a test cookie 
// and looking to see if it exists. 
// CREATED: 2003-07-21
//----------------------------------------------------------------------
function cookiesEnabled ( ) {
	setCookie ( "temp", "1", 86400 ); // 1 day required for IE4 for Mac
	if ( getCookieData ( "temp" ) ) {
		return true;
	} else {
		return false;
	}
}

//----------------------------------------------------------------------
// FUNCTION: setMarker
// INPUT: 
// OUTPUT: cookie
// DESCRIPTION: Creates a cookie to mark the current Request URI, including variables.
// CREATED: 2003-05-21
//----------------------------------------------------------------------
function setMarker ( pathIndex ) { 
	if ( isEmpty ( pathIndex ) ) pathIndex = "";

	var path = escape ( location.pathname );
	path += escape ( location.search );

	cookieStr  = "marker" + pathIndex + "=" + path; //-- Eliminate spaces in cookies.
	cookieStr += "; path=/";
	document.cookie = cookieStr;
}

//----------------------------------------------------------------------
// FUNCTION: backTrack
// INPUT: 
// OUTPUT: Go back to previous page
// DESCRIPTION: Looks for marker cookie and goes back to that URI, using 
// href or assign, not pathname or search (which need to combine to make
// up the URI. If not found, it goes back to the last page in history. 
// CREATED: 2003-05-21
//----------------------------------------------------------------------
function backTrack ( pathIndex ) {
	if ( isEmpty ( pathIndex ) ) pathIndex = "";

	var markerName = "marker" + pathIndex;
	var marker = getCookieData ( markerName );
	delCookie ( markerName );
	
	if ( marker ) {
		window.location.href = marker;
	} else {
		history.back ( );
	}
}

//----------------------------------------------------------------------
// FUNCTION: doSetCookie
// INPUT: name, value, interval, path
// OUTPUT: cookie
// DESCRIPTION: More detailed version of setCookie, for testing
// CREATED: 2003-08-20
//----------------------------------------------------------------------
function doSetCookie ( name, value, interval, path ) { 
	//-- interval must be in seconds. 
	interval = interval * 1000; //-- Change to milliseconds for setTime.
	var expiration = new Date ( );
	var timeInt = expiration.getTime ( ) + interval
	expiration.setTime ( timeInt );
	cookieStr = name + "=" + value; //-- Eliminate spaces in cookies.
	cookieStr += "; expires=";
	cookieStr += expiration.toGMTString ( );
	cookieStr += "; path=";
	cookieStr += path;
	document.cookie = cookieStr;
}

//----------------------------------------------------------------------
// FUNCTION: store2list
// INPUT: value, cookieName, isRepeatable, doSort, interval (seconds)
// OUTPUT: cookie
// DESCRIPTION: Adds the value to a list of data stored in a cookie.
// CREATED: 2005-01-11
//----------------------------------------------------------------------
function store2list ( value, cookieName, isRepeatable, doSort, interval ) { 
	var myData = getCookieData ( cookieName );
	if ( myData ) {
		var dataStr = hex2str ( myData );
		var contentArray = dataStr.split ( "|" );
	} else {
		var contentArray = new Array ( );
	}
	
	// Add to value to array.
	if ( !isRepeatable ) {
		// See if value is already there.
		var inTHERE = false;
		for ( var i = 0; i < contentArray.length; i++ ) { 
			if ( contentArray[i] == value ) inTHERE = true;
		}
		if ( !inTHERE ) {
			contentArray[contentArray.length] = value; // push doesn't work in IE5 for Mac	
		}
	} else {
		contentArray[contentArray.length] = value; // push doesn't work in IE5 for Mac	
	}
	
	// Sort array.
	if ( doSort ) contentArray.sort ( compare );
	
	// Encode into Hex and store.
	var newData = str2hex ( contentArray.join ( "|" ) );
	setCookie ( cookieName, newData, interval );
	return newData;
}

//----------------------------------------------------------------------
// SHOPPING CART FUNCTIONS
//----------------------------------------------------------------------
// FUNCTION: item (object)
// INPUT: index, id, qty, instrSrc, instr, isCustom, price
// OUTPUT: 
// DESCRIPTION: Object constructor populates properties. 
// CREATED: 2003-06-12
// 2003-07-23: Add index ID, not stored in Cookie but inferred at parse time.
//----------------------------------------------------------------------
function item ( id, productID, pieceID, summary, qty, instrSrc, instr, isCustom, price ) { 
	this.id 		= id;
	this.productID 	= productID;
	this.pieceID 	= pieceID;
	this.summary 	= summary;
	this.qty 		= parseInt ( qty );
	this.instrSrc 	= instrSrc;
	this.instr 		= instr;
	this.isCustom 	= isCustom;
	this.price 		= price;
}

//----------------------------------------------------------------------
// FUNCTION: add_n_items
// INPUT: cartName, productID, pieceID, summary, myQty
// OUTPUT: Update cookie
// DESCRIPTION: Add a single item to the count. Mainly used by links w/o forms.
// CREATED: 2006-10-17
// 2007-04-13: Add cartName and myQty variables. myQty == 0 triggers prompt.
//----------------------------------------------------------------------
function add_n_items ( cartName, productID, pieceID, summary, myQty ) {
	// Zero qty triggers Prompt. 
	if ( myQty == 0 ) {
		var response = prompt ( "Quantity to add to cart of \r'" + summary + "'?", 1 );
	 	myQty = parseInt ( parseOutAlpha ( response ) );
	}
	if ( myQty < 1 ) myQty = 1;
	var cartArray = new getCartArray ( cartName );

	var instrSrc = "";
	var isCustom = 0;
	var price = 0;
	var i = 0;
	var totalQty = 0;
	if ( cartArray.length > i ) {
	// ADD TO CART THAT ALREADY HAS ITEMS
		// Parse cart to find matching product/piece
		var isFound = false;
		for ( var i = 0; i < cartArray.length && !isFound; i++ ) {
			// If found, then add quantity
			if ( productID == cartArray[i].productID && pieceID == cartArray[i].pieceID ) {
				isFound = true;
				cartArray[i].qty += myQty;
				totalQty = cartArray[i].qty;
			}
		}
		
		// If no matching product is found, add this item to the cart.
		if ( !isFound ) {
			var myItem = new item ( i, productID, pieceID, summary, myQty, instrSrc, "", isCustom, price );
			cartArray[i] = myItem;
			totalQty = myQty;
		}
	} else {
	// ADD TO EMPTY CART
		var myItem = new item ( i, productID, pieceID, summary, myQty, instrSrc, "", isCustom, price );
		var cartArray = new Array ( myItem );
		totalQty = myQty;
	}

	setCart ( cartName, cartArray );
	alert ( "Total of " + totalQty + " units \r" + summary + "." );	
//	history.go ( 0 );
}

//----------------------------------------------------------------------
// FUNCTION: addItem
// INPUT: cartname, productID, pieceID, summary, myForm, qtyIndex, instrSrc
// OUTPUT: Update cookie
// DESCRIPTION: Add item entry to cart and set cart cookie.
// CREATED: 2003-06-12
// array.push() & array.pop() are broken in IE5 for Mac. Work around.
// 2007-04-13: Add cartName variable. 
//----------------------------------------------------------------------
function addItem ( cartName, productID, pieceID, summary, myForm, qtyIndex, instrSrc ) { 
	var myQty = parseInt ( myForm.elements[qtyIndex].value );
	var cartArray = new getCartArray ( cartName );
	var i = 0;
	if ( cartArray.length > i ) {
		var isFound = false;
		for ( var i = 0; i < cartArray.length && !isFound; i++ ) {
			if ( productID == cartArray[i].productID && pieceID == cartArray[i].pieceID ) {
				if ( cartArray[i].instrSrc == "" ) {				
					isFound = true;
					cartArray[i].qty += myQty;
				}
			}
		}
		if ( !isFound ) {
			var myItem = new item ( i, productID, pieceID, summary, myQty, instrSrc, "" );
			cartArray[i] = myItem;
		}
	} else {
		var myItem = new item ( i, productID, pieceID, summary, myQty, instrSrc, "" );
		var cartArray = new Array ( myItem );
	}

	setCart ( cartName, cartArray );
	
	if ( instrSrc == "" ) {
		history.go ( 0 );
	} else {
		setMarker ( "" );
		window.location.href = "/products/details.php?id=" + i + "&instr=" + instrSrc;
	}
}

//----------------------------------------------------------------------
// FUNCTION: chQty
// INPUT: id, qty
// OUTPUT: alert
// DESCRIPTION: Provides a way to discretely update just quantity of items.
// CREATED: 2007-08-09
//----------------------------------------------------------------------
function chQty ( productID, pieceID, qty ) {
	// DELETE ITEM IF QTY == 0
	if ( qty == 0 ) {
		newQty = 0;
	
	// ELSE Ask for new quantity.
	} else {
		var newQty = prompt ( "How many items?", qty );
		newQty = parseInt ( parseOutAlpha ( newQty ) );
	}
	
	// Load script page to execute. 
	// NOTE: Must use same page to run script because of fault in 
	// IE and Firefox that won't allow reload() after setting cookie. 	
	var oldLoc = window.location.href;
	var newLoc = "1_cart.php";
	newLoc += "?productID=" + productID;
	newLoc += "&pieceID=" + pieceID;
	newLoc += "&qty=" + newQty;
	setMarker ( "" );
	window.location.href = newLoc;
	
	// Return to Cart Page
	//window.location.href = oldLoc;
	//window.location.reload ( );
}

//----------------------------------------------------------------------
// FUNCTION: changeItem
// INPUT: id, myForm, qtyIndex
// OUTPUT: Update cookie
// DESCRIPTION: Change item entry's qty and reset cart cookie.
// CREATED: 2003-06-12
// array.push() & array.pop() are broken in IE5 for Mac. Work around.
// 2007-04-13: Add cartName variable. 
//----------------------------------------------------------------------
function changeItem ( cartName, id, productID, pieceID, summary, myQty, instrSrc, instr, isCustom, price ) { 
	var cartArray = new getCartArray ( cartName );
	if ( cartArray.length > id ) {		
		cartArray[id].productID = productID;
		cartArray[id].pieceID 	= pieceID;
		cartArray[id].summary 	= summary;
		cartArray[id].qty 		= myQty;
		cartArray[id].instrSrc 	= instrSrc;
		cartArray[id].instr 	= instr;
		cartArray[id].isCustom 	= isCustom;
		cartArray[id].price 	= price;
	} else {
		alert ( "The contents of the cart have been reduced unexpectectedly." )
	}
	
	setCart ( cartName, cartArray );
}

//----------------------------------------------------------------------
// FUNCTION: delItem
// INPUT: id
// OUTPUT: Update cookie
// DESCRIPTION: Delete all occurances of item entry from cart and set cart cookie.
// CREATED: 2003-06-14
// array.push() & array.pop() are broken in IE5 for Mac. Work around.
// 2007-04-13: Add cartName variable. 
//----------------------------------------------------------------------
function delItem ( cartName, myID ) { 
	var cartArray = new getCartArray ( cartName );
	var newCartArray = new Array ( );
	var j = 0;
	if ( cartArray.length > 0 ) {
		for ( var i = 0; i < cartArray.length; i++ ) {
			if ( cartArray[i].id != myID ) {
				newCartArray[j++] = cartArray[i];
			}
		}
	
		setCart ( cartName, newCartArray );
	}
	setMarker ( "" );
	window.location.href = newLoc;
}

//----------------------------------------------------------------------
// FUNCTION: submitItem
// INPUT: myForm
// OUTPUT: Update cookie
// DESCRIPTION: Change item from Details form.
// CREATED: 2003-07-24
//----------------------------------------------------------------------
function submitItem ( cartName ) { 
	var myForm = document.detailsForm;
	
	var id 			= myForm.id.value;
	var productID 	= myForm.productID.value;
	var pieceID 	= myForm.pieceID.value;
	var summary 	= myForm.summary.value;
	var myQty 		= myForm.qty.value;
	var instrSrc 	= myForm.instrSrc.value;
	var instr 		= myForm.instructions.value;
	var isCustom	= myForm.isCustom.value;
	var price		= myForm.price.value;
	changeItem ( cartName, id, productID, pieceID, summary, myQty, instrSrc, instr );
}

//----------------------------------------------------------------------
// FUNCTION: getCartArray
// INPUT: cartName
// OUTPUT: cartArray or false
// DESCRIPTION: Read cart cookie and decrypt data to array.
// CREATED: 2003-06-12
// 2007-04-13: Add variable cart name.
// 2007-08-10: Switch to 2D array. 
//----------------------------------------------------------------------
function getCartArray ( cartName ) { 
	var cartData = getCookieData ( cartName );

	if ( cartData ) {
		// Break into arguments of two dimensions.
		var cartArray = cartData.split ( ":" );	
		
		var j = 0;
		for ( var i = 0; i < cartArray.length; i++ ) { 
			var lineArray = new Array ( );
			lineArray = cartArray[i].split ( "." );
			
			// Use if statement to filter corrupt entries
			if ( lineArray.length == 8 && lineArray[0].length > 0 ) { 
				var productID 	= hex2str ( lineArray[0] );
				var pieceID 	= hex2str ( lineArray[1] );
				var summary 	= hex2str ( lineArray[2] );
				var qty 		= hex2str ( lineArray[3] );
				var instrSrc 	= hex2str ( lineArray[4] );
				var instr 		= hex2str ( lineArray[5] );
				var isCustom	= hex2str ( lineArray[6] );
				var price		= hex2str ( lineArray[7] );
		
				cartArray[j] = new item ( j, productID, pieceID, summary, qty, instrSrc, instr, isCustom, price );
				j++;
			}
		}
	} else {
		var cartArray = new Array ( );
	}
	return cartArray;	
}

//----------------------------------------------------------------------
// FUNCTION: setCart
// INPUT: cartArray
// OUTPUT: cookie
// DESCRIPTION: Creates a cookie to mark the current Request URI, including variables.
// CREATED: 2003-05-21
// array.push() & array.pop() are broken in IE5 for Mac. Work around.
// 2007-04-13: Add cartName variable. 
// 2007-08-10: Revise to 2D array. 
//----------------------------------------------------------------------
function setCart ( cartName, cartArray ) { 
	var lineArray = new Array ( );
	var cart2Darray = new Array ( );
	var j = 0;
	for ( var i = 0; i < cartArray.length; i++ ) {
		lineArray[0] = str2hex ( cartArray[i].productID );
		var productID = cartArray[i].productID;
		
		lineArray[1] = str2hex ( cartArray[i].pieceID );
		var pieceID = cartArray[i].pieceID;
		
		lineArray[2] = str2hex ( cartArray[i].summary );
		lineArray[3] = str2hex ( cartArray[i].qty );
		lineArray[4] = str2hex ( cartArray[i].instrSrc );
		lineArray[5] = str2hex ( cartArray[i].instr );
		lineArray[6] = str2hex ( cartArray[i].isCustom );
		lineArray[7] = str2hex ( cartArray[i].price );
		cart2Darray[i] = lineArray.join ( "." );
		j = 0;
	}
	
	var cartData = cart2Darray.join ( ":" );
	var interval = 60 * 60 * 24 * 30; //-- Keep cart for 30 days
	setCookie ( cartName, cartData, interval );

	return cartData;
}

//----------------------------------------------------------------------
// FUNCTION: checkRedundant
// INPUT: myInput, redundantStr
// OUTPUT: 
// DESCRIPTION: If string matches value, delete and alert.
// CREATED: 2003-08-02
//----------------------------------------------------------------------
function checkRedundant ( myInput, redundantStr ) {
	 if ( myInput.value == redundantStr ) {
	 	myInput.value = "";
	 	alert ( "Product style should not be the same as the product name.\rUnless a color or other material style applies, it's best to leave this field blank." );
	 }
}

//----------------------------------------------------------------------
// FUNCTION: syncAddresses
// INPUT: bill2ship, myForm
// OUTPUT: bill2shipON
// DESCRIPTION: Checks checkbox and copies bill address to ship address
// if ON, disabling shipping address. If off, enables shipping address.
// CREATED: 2003-07-11
//----------------------------------------------------------------------
function syncAddresses ( bill2ship, myForm ) { 
	if ( bill2ship.checked ) {
		myForm.street1_1.value 			= myForm.street1_0.value;
		myForm.street2_1.value 			= myForm.street2_0.value;
		myForm.city_1.value 			= myForm.city_0.value;
		myForm.state_1.selectedIndex 	= myForm.state_0.selectedIndex;
		myForm.zip_1.value 				= myForm.zip_0.value;

		myForm.street1_1.disabled 	= true;
		myForm.street2_1.disabled 	= true;
		myForm.city_1.disabled 		= true;
		myForm.state_1.disabled 	= true;
		myForm.zip_1.disabled 		= true;
	} else {
		myForm.street1_1.disabled 	= false;
		myForm.street2_1.disabled 	= false;
		myForm.city_1.disabled 		= false;
		myForm.state_1.disabled 	= false;
		myForm.zip_1.disabled 		= false;
	}
}

//----------------------------------------------------------------------
// XML FUNCTIONS
//----------------------------------------------------------------------


//----------------------------------------------------------------------
// OBSOLETE FUNCTIONS
//----------------------------------------------------------------------
function comma2dec(Vnum) { //-- UPDATED 2001-12-05
	
	var signage = "";
	if ( Vnum < 0 ) {
		Vnum = Math.abs(Vnum);
		signage = "-";
	}
	if(Vnum > 99990000) {
		alert("That number is outside legalparameters.");
		focus();
	} else {
	
		var V10million =parseInt(Vnum / 10000000);

		var V1million = (Vnum % 10000000)  / 1000000;
		if(V1million / 1000000 == 1) {
			V1million = 1;
		} else if(V1million < 1) {
			V1million = "0";
		} else {
			V1million =parseInt(V1million,10);
		}

		var V100thousand = (Vnum % 1000000)  / 100000;
		if(V100thousand / 100000 == 1) {
			V100thousand = 1;
		} else if(V100thousand < 1) {
			V100thousand = "0";
		} else {
			V100thousand =parseInt(V100thousand,10);
		}

		var V10thousand = (Vnum % 100000)  / 10000;
		if(V10thousand / 10000 == 1) {
			V10thousand = 1;
		} else
			if(V10thousand < 1) {
			V10thousand = "0";
		} else {
			V10thousand =parseInt(V10thousand,10);
		}

		var V1thousand = (Vnum % 10000)  / 1000;
		if(V1thousand / 1000 == 1) {
			V1thousand = 1;
		} else if(V1thousand < 1) {
			V1thousand = "0";
		} else {
			V1thousand =parseInt(V1thousand,10);
		}

		var Vhundreds = (Vnum % 1000)  / 100;
		if(Vhundreds / 100 == 1) {
			Vhundreds = 1;
		} else if(Vhundreds < 1) {
			Vhundreds = "0";
		} else {
			Vhundreds =parseInt(Vhundreds,10);
		}

		var Vtens = (Vnum % 100)  / 10;
		if(Vtens / 10 == 1) {
			Vtens = 1;
		} else if(Vtens < 1) {
			Vtens = "0";
		} else {
			Vtens =parseInt(Vtens,10);
		}

		var Vones = (Vnum % 10)  / 1;
		if(Vones / 1 == 1) {
			Vones = 1;
		} else if(Vones < 1) {
			Vones = "0";
		} else {
			Vones =parseInt(Vones,10);
		}

		var Vcents =parseInt((((Vnum % 1) * 100)+0.5),10);

		if(Vcents < 1) {
			Vcents = "00";
		} else if(Vcents % 10 == 0) {
			Vcents = Vcents + "0";
		} else if(Vcents % 10 == Vcents) {
			Vcents = "0" + Vcents;
		} else {
			Vcents = Vcents;
		}

		if(Vcents == "900") {
			Vcents = "90";
		} else if(Vcents == "800") {
			Vcents = "80";
		} else if(Vcents == "700") {
			Vcents = "70";
		} else if(Vcents == "600") {
			Vcents = "60";
		} else if(Vcents == "500") {
			Vcents = "50";
		} else if(Vcents == "400") {
			Vcents = "40";
		} else if(Vcents == "300") {
			Vcents = "30";
		} else if(Vcents == "200") {
			Vcents = "20";
		} else if(Vcents == "100") {
			Vcents = "10";
		} else {
			Vcents = Vcents;
		}

		var Vformat = "";

		if(Vnum >= 10000000) {
			Vformat = (V10million + "" + V1million + "," + V100thousand + "" + V10thousand + "" + V1thousand + "," + Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 1000000) {
			Vformat = (V1million + "," + V100thousand + "" + V10thousand + "" + V1thousand + "," + Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 100000) {
			Vformat = (V100thousand + "" + V10thousand + "" + V1thousand + "," + Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 10000) {
			Vformat = (V10thousand + "" + V1thousand + "," + Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 1000) {
			Vformat = (V1thousand + "," + Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 100) {
			Vformat = (Vhundreds + "" + Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 10) {
			Vformat = (Vtens + "" + Vones + "." + Vcents);
		} else if(Vnum >= 1) {
			Vformat = (Vones + "." + Vcents);
		} else {
			Vformat = ("0." + Vcents);
		}

		Vformat = signage + Vformat;
		return Vformat;

	}
}
