//	San Juan Nature Institute - Javascript routines supporting shopping cart activity

	// Compute extended cost for a shopping cart line item
	// Notes:	A SJNI database entry includes a cost element for that workshop or product.
	//			The cost element consists of 'triplets' delimited by verticals bar |. Each 'triplet' consists of three components delimited by colons :
	//			Example:  "Tuition:$55.00:((qty*55)-arg1)|Lunch:$15.00:(qty*15)|Ferry:$14.00:(14)" =  Class fee $55 (with discount potential) with lunch @ $15/student plus one $14 ferry ticket reimbursement
	//
	//			Cart entries are a triplet consisting of the DB-key, indicators for which cost options are selected, and arguments for quantity and any others passed from the reservation page
	//			Example: "BOT0621:true,false,false:2,5"  combined with the above DB Cost entry = 2 enrollments, tuituion cost for each is $55 minus a $5 discount
	//
	//			If any problems occur in processing extended cost, the result returned is NULL (not zero)			
	function computeExtCost(pattern,args) {
		var i, result;
		var formula=pattern;																					// initialize the formula to be evaluated
		var arg=args.split(',');																				// split the arguments into an array
		if ((arg.length==0)||(arg[0]=='')) return null;															// if no arguments exist, return null (problem)
		formula=formula.replace(/qty/gi,arg[0]);																// replace each occurance of 'qty' with the value of the argument 0
		for (i=1; i<arg.length; i++) { eval('formula=formula.replace(/arg' + i + '/gi,arg[' + i + '])'); }		// replace each argN with the value of arg[N]
		try { result=eval(formula);	} catch (err) {	return null; }												// evaluate the formula to derive a numeric result (if a problem occurs, return null)
		return result;																							// return the result
	}

	// list the contents of the shopping cart
	// Notes:	used in forms to allow editing of qty or removal of items
	function listCart(cart) {
		var i, ii, DBobj, extcost;
		var cartitem, cartcount, cartdetail, costitem, costdetail, costoption, costarg;
		var totalcost=0;
		cartitem=cart.split('|');
		cartcount=cartitem.length;
		if ((cartitem[0]==null)&&(cartcount==1)) cartcount=0;
		if (cartcount==0) return;
		/* output each item in the cart */
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			if (i%2==0) document.write('<tr>');
			if (i%2!=0) document.write('<tr class="altrowhilite">');
			document.write('  <td align="center" valign="middle"><input type="text" size="2" maxlength="2" name="qty'+i+'" value="' + costarg[0] + '" onChange="editQty(this);markCart('+i+');" onKeyPress="return qtyOnKeyPress(event,'+i+');"></td>');
			if ((DBobj.entrytype.toLowerCase()=='c')||(DBobj.entrytype.toLowerCase()=='y')) document.write('  <td align="left" valign="middle">&nbsp;'+DBobj.mmddyy+' '+DBobj.title+' ('+DBobj.island+')</td>');
			if (DBobj.entrytype.toLowerCase()=='s') document.write('  <td align="left" valign="middle">&nbsp;'+DBobj.title+'</td>');
			document.write('  <td align="right" valign="middle">');
			document.write('    <table width="100%" border="0" cellpadding="0" cellspacing="0">');
			/* output a line for each cost element in the cart item */
			for (ii=0; ii<costoption.length; ii++) {
				if (costoption[ii].substr(0,1).toLowerCase()!='t') continue;
				costdetail=costitem[ii].split(':');
				if ((costdetail[0]!=null)&&(costdetail[1]!=null)) {
					document.write('    <tr><td align="left" valign="middle" nowrap>&nbsp;'+costdetail[0]+'</td>');
					document.write('    <td align="right" valign="middle" nowrap>'+costdetail[1]+'&nbsp;</td></tr>');
				}
			}
			document.write('    </table>');
			document.write('  </td>');
			document.write('  <td id="cartextcost'+i+'" align="right" valign="middle">');
			document.write('    <table width="100%" border="0" cellpadding="0" cellspacing="0">');
			/* output a line for each extended oost element in the cart item */
			for (ii=0; ii<costoption.length; ii++) {
				if (costoption[ii].substr(0,1).toLowerCase()!='t') continue;
				costdetail=costitem[ii].split(':');
				if ((costdetail[0]!=null)&&(costdetail[2]!=null)) {
					/* compute the extended cost based on one of several formulas */
					extcost=computeExtCost(costdetail[2],cartdetail[2]);
					if (extcost==null) {
						document.write('    <tr><td align="right" valign="middle" nowrap class="redtext">== Error ==&nbsp;</td></tr>');
					} else {
						totalcost=totalcost+extcost;
						document.write('    <tr><td align="right" valign="middle" nowrap>$'+currencyFormatter(extcost,true)+'&nbsp;</td></tr>');
					}
				}
			}
			document.write('    </table>');
			document.write('  </td>');
			/* output the delete-me checkbox */
			document.write('  <td align="center" valign="top"><input type="checkbox" name="remove'+i+'" value="Y" onClick="markCart('+i+');"></td>');
			document.write('</tr>');
		}	// end: each item in the cart
		/* output the cart total line */
		document.write('<tr><td colspan="5"><hr size="1" width="600" color="#999999"></td></tr>');
		document.write('<tr>');
		document.write('  <td colspan="3" id="carttotalhead" align="right" valign="top" nowrap style="font-weight:bold">Total:&nbsp;</td>');
		document.write('  <td id="carttotal" align="right" valign="top" nowrap style="font-weight:bold">$'+currencyFormatter(totalcost,true)+'&nbsp;</td>');
		document.write('  <td>&nbsp;</td>');
		document.write('</tr>');
		document.write('<tr><td colspan="5" height="1" bgcolor="#336633"><img src="images/1px.gif" width="1" height="1" border="0" alt=""></td></tr>');
	}

	// detects and processes which key is pressed while editing the qty field.
	function qtyOnKeyPress(evt,theIndex) {
		if ((evt)&&(evt.which)) {					// if 'which' property of event object is supported (NN4)
			if (evt.which==13) return false;		// if enter key, return false to suppress automatic submit (e.g.ignore this keystroke)
		}
		if (evt.keyCode==13) return false;			// if browser doesn't recognise the 'which' property try the 'keycode' property  (IE)
		markCart(theIndex);							// otherwise mark this item as pending update, hide the checkout button, etc.
		return true;								// return true to pass the keystroke
	}

	// Mark the cart as pending update (follows a quantity change)
	// Notes:	used when changes are pending from the form that used the ListCart procedure above.
	function markCart(theIndex) {
		var theObj;
		theObj=SJNI_findObj('coBtn');
		if (theObj!=null) theObj.style.display='none';
		theObj=SJNI_findObj('updBtn');
		if (theObj!=null) theObj.style.display='block';
		theObj=SJNI_findObj('cartextcost'+theIndex);
		if (theObj!=null) theObj.innerHTML='<span class="tinytxt">pending update</span>&nbsp;';
		theObj=SJNI_findObj('carttotal');
		if (theObj!=null) theObj.innerHTML='<span class="tinytxt">pending update</span>&nbsp;';
		// theObj=SJNI_findObj('carttotalhead');
		// if (theObj!=null) theObj.innerHTML='Total is pending update:&nbsp;';
	}

	// Quantity Edit
	function editQty(theElement) {
		var theQty = theElement.value;							// extract the quantity field from the form
		theQTY=theQty.replace(' ','');							// treat spaces as if nulls
		if (parseInt(theQty)==0) {								// ignore zero value (treat as if null)
			theElement.value='';
			theQty='';
		}
		if (theQty.length==0) {									// if the field is empty there is nothing to check, we're done
			return true;
		} else {												// otherwise edit for an acceptable integer value (errors return with false result)
			if (isNaN(theQty)) {
				alert("The Quantity Must Be Numeric");
				return false;
			} else {
				if ((isNaN(parseInt(theQty)))||(parseInt(theQty)==0)) {
					alert("An Invalid Quantity Was Entered");
					return false;
				} else {										// no error detected, replace the form field with the numeric result
					theElement.value = parseInt(theQty);
				}
			}
		}
		return true;											// no error detected, return true result code
	}

	// Update the cart
	function updateQty(whichForm,whichButton,xmitForm,cart) {
		var theObj, errDetected, newitem, newcart, cartdetail;
		var cartitem=cart.split('|');
		var cartcount=cartitem.length;
		if ((cartitem[0]==null)&&(cartcount==1)) cartcount=0;
		if (cartcount==0) return;
		newcart='';
		for (i=0; i<cartitem.length; i++) {
			// if an invalid cart entry has somehow been added to the cart, skip it
			if (!validCart(cartitem[i])) continue;
			// If the remove checkbox is checked, null the quantity entry (this will cause it to be skipped)
			theObj=eval(whichForm+'.remove'+i);
			if (theObj.checked) {
				theObj=eval(whichForm+'.qty'+i);
				theObj.value='';
			}					
			theObj=eval(whichForm+'.qty'+i);
			errDetected = !editQty(theObj);
			if (errDetected) break;
			// edits passed but if qty is now null we don't need to do anything more, skip this item
			if ((theObj.value.length==0)||(theObj.value==null)) continue;
			// edits passed and qty is non-zero; add the item to the replacement cart string
			cartdetail=cartitem[i].split(':');
			if (cartdetail[2].indexOf(',')<0) { 
				cartdetail[2]=theObj.value;
			} else {
				cartdetail[2]=theObj.value+','+cartdetail[2].substring(cartdetail[2].indexOf(',')+1);
			}
			newitem=cartdetail[0]+':'+cartdetail[1]+':'+cartdetail[2];
			if (newcart.length!=0) newcart=newcart+'|';
			newcart=newcart+newitem;
		}	// end processing cart items
		// We're done processing the cart entries. If an error was detected exit now
		// Otherwise, make the button that called this routine disappear then insert the new cart into the transmittal form and submit it
		if (errDetected) return;
		if (whichButton.length>0) {
			theObj=SJNI_findObj(whichButton);
			if (theObj!=null) theObj.style.display='none';
		}
		if (xmitForm.length>0) {
			theObj=SJNI_findObj(xmitForm);
			if (theObj!=null) {
				theObj.cartrepl.value=newcart;
				if (newcart=='') theObj.cartinit.value='Y'
				theObj.submit();
			}
		}
	}

	// Call the Checkout page from the cart edit form
	function checkOut(whichButton) {
		if (whichButton.length>0) {
			theObj=SJNI_findObj(whichButton);
			if (theObj!=null) theObj.style.display='none';
		}
		window.location='checkout.php';
	}

	// list the contents of the shopping cart
	// Notes:	used to display cart without options for changing qty or removing items
	function displayCart(cart) {
		var i, ii, DBobj, extcost;
		var cartitem, cartcount, cartdetail, costitem, costdetail, costoption, costarg;
		var totalcost=0;
		cartitem=cart.split('|');
		cartcount=cartitem.length;
		if ((cartitem[0]==null)&&(cartcount==1)) cartcount=0;
		if (cartcount==0) return;
		/* output each item in the cart */
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			if (i%2==0) document.write('<tr>');
			if (i%2!=0) document.write('<tr class="altrowhilite">');
			document.write('  <td align="center" valign="top">'+costarg[0]+'</td>');
			if ((DBobj.entrytype.toLowerCase()=='c')||(DBobj.entrytype.toLowerCase()=='y')) document.write('  <td align="left" valign="top">&nbsp;'+DBobj.mmddyy+', '+DBobj.title+' ('+DBobj.island+')</td>');
			if (DBobj.entrytype.toLowerCase()=='s') document.write('  <td align="left" valign="top">&nbsp;'+DBobj.title+'</td>');
			document.write('  <td align="right" valign="top">');
			document.write('    <table width="100%" border="0" cellpadding="0" cellspacing="0">');
			/* output a line for each cost element in the cart item */
			for (ii=0; ii<costoption.length; ii++) {
				if (costoption[ii].substr(0,1).toLowerCase()!='t') continue;
				costdetail=costitem[ii].split(':');
				if ((costdetail[0]!=null)&&(costdetail[1]!=null)) {
					document.write('    <tr><td align="left" valign="top" nowrap>&nbsp;'+costdetail[0]+'</td>');
					document.write('    <td align="right" valign="top" nowrap>'+costdetail[1]+'&nbsp;</td></tr>');
				}
			}
			document.write('    </table>');
			document.write('  </td>');
			document.write('  <td align="right" valign="top">');
			document.write('    <table width="100%" border="0" cellpadding="0" cellspacing="0">');
			/* output a line for each extended oost element in the cart item */
			for (ii=0; ii<costoption.length; ii++) {
				if (costoption[ii].substr(0,1).toLowerCase()!='t') continue;
				costdetail=costitem[ii].split(':');
				if ((costdetail[0]!=null)&&(costdetail[2]!=null)) {
					/* compute the extended cost based on one of several formulas */
					extcost=computeExtCost(costdetail[2],cartdetail[2]);
					if (extcost==null) {
						document.write('    <tr><td align="right" valign="top" nowrap class="redtext">== Error ==&nbsp;</td></tr>');
					} else {
						totalcost=totalcost+extcost;
						document.write('    <tr><td align="right" valign="top" nowrap>$'+currencyFormatter(extcost,true)+'&nbsp;</td></tr>');
					}
				}
			}
			document.write('    </table>');
			document.write('  </td>');
			document.write('</tr>');
		}
		/* output the cart total line */
		document.write('<tr><td colspan="4"><hr size="1" width="540" color="#999999"></td></tr>');
		document.write('<tr>');
		document.write('  <td colspan="3" align="right" valign="top" nowrap style="font-weight:bold">Total:&nbsp;</td>');
		document.write('  <td align="right" valign="top" nowrap style="font-weight:bold">$'+currencyFormatter(totalcost,true)+'&nbsp;</td>');
		document.write('</tr>');
		document.write('<tr><td colspan="4"><hr size="1" width="100%" color="#336633"></td></tr>');
	}

	// Prepare the reservation form data for tranmittal to the confirmation page.
	function prepConfirm(formObj,cart) {
		// Name must be entered
		if (formObj.bill_to_name.value=='') {
			alert('Please Enter Your Name');
			formObj.bill_to_name.focus();
			return false;
		}
		// A Phone or E-mail must be entered
		if (formObj.email.value=='') {
			if (formObj.phone.value=='') {
				alert('Please Enter Your Phone Number or E-mail Address');
				formObj.phone.focus();
				return false;
			}
		}
		// If an e-mail address is provided, do we recognize the format?
		if (formObj.email.value!='') {
			if (!validateEmail(formObj.email.value)) {
				alert('E-mail address format is not recognized (e-mail address is not required if you provide a phone number)');
				formObj.email.focus();
				return false;
			}
		}
		// A Payment type must be checked
		var i;
		var pymt=-1;
		for (i=0; i<formObj.payment_type.length; i++) {
			if (formObj.payment_type[i].checked) pymt=i;
		}
		if (pymt==-1) {
			alert('Please Select A Payment Type');
			formObj.payment_type[0].focus();
			return false;
		}
		// all required fields are present, now load the cart details into the form
		formObj.submitBtn.style.display='none';
		var i, ii, DBobj, extcost, firstopt;
		var cartitem, cartcount, cartdetail, costitem, costdetail, costoption, costarg;
		var totalcost=0;
		var orderdetail='';
		cartitem=cart.split('|');
		cartcount=cartitem.length;
		if ((cartitem[0]==null)&&(cartcount==1)) cartcount=0;
		if (cartcount==0) return false;
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			firstopt=true;
			for (ii=0; ii<costoption.length; ii++) {
				if (costoption[ii].substr(0,1).toLowerCase()!='t') continue;
				costdetail=costitem[ii].split(':');
				if ((costdetail[0]!=null)&&(costarg[0]!=null)) {
					if (firstopt) {
						firstopt=false;
						if (orderdetail.length>0) orderdetail=orderdetail+'<CRLF>';
						orderdetail=orderdetail+'Item #'+(i+1)+':  qty='+costarg[0]+', '+DBobj.title;
						if ((DBobj.entrytype.toLowerCase()=='c')||(DBobj.entrytype.toLowerCase()=='y')) orderdetail=orderdetail+'  '+DBobj.mmddyy+'  '+DBobj.island;
					}
					extcost=computeExtCost(costdetail[2],cartdetail[2]);
					if (extcost==null) {
						orderdetail=orderdetail+'<CRLF>     '+costdetail[0]+': ERROR COMPUTING EXTENDED COST';
					} else {
						totalcost=totalcost+extcost;
						orderdetail=orderdetail+'<CRLF>     '+costdetail[0]+': $'+currencyFormatter(extcost);
					}
				} // end: non-null cost detail
			} // end: cost items in cart item
		}	// end: cart item
		formObj.order_detail.value=orderdetail;
		formObj.order_total.value='$'+currencyFormatter(totalcost);
		formObj.submit();
		return false;
	}

	// summarize the contents of the shopping cart
	// Notes:	used on the confirmation page
	function cartSummary(cart) {
		var i, firstline, awynp, DBobj;
		var cartitem, cartcount, cartdetail, costitem, costdetail, costoption, costarg;
		cartitem=cart.split('|');
		cartcount=cartitem.length;
		if ((cartitem[0]==null)&&(cartcount==1)) cartcount=0;
		if (cartcount==0) return;
		/* summarize product purchases */
		firstline=true;
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			if (DBobj.entrytype.toLowerCase()!='s') continue;
			if (firstline) {
				firstline=false;
				document.write('<tr><td align="left" valign="top">');
				document.write('<span class="largertxtbold">&bull; Your order has been received for the following items:</span><br>');
			}
			document.write('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+costarg[0]);
			document.write(' <em>'+DBobj.title+'</em><br>');
		}
		if (!firstline) document.write('</td></tr>');
		/* summarize waorkshop or young naturalist programs */
		awynp=false;
		firstline=true;
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			if (DBobj.entrytype.toLowerCase()!='c') continue;
			awynp=true;
			if (firstline) {
				firstline=false;
				document.write('<tr><td align="left" valign="top">');
				document.write('<span class="largertxtbold">&bull; Space has been reserved in the following Adult Workshops:</span><br>');
			}
			document.write('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+costarg[0]);
			if (costarg[0]==1) document.write(' participant, ');
			if (costarg[0]>1) document.write(' participants, ');
			document.write(DBobj.mmddyy+', <em>'+DBobj.title+'</em>, on '+DBobj.island+' Island, '+'<br>');
		}
		if (!firstline) document.write('</td></tr>');
		/* summarize Young Naturalist enrollments */
		firstline=true;
		for (i=0; i<cartitem.length; i++) {
			if (!validCart(cartitem[i])) continue;				// if not a valid cart entry, go on to the next one
			cartdetail=cartitem[i].split(':');					// split the cart item into it's details, delimiter is :
			costoption=cartdetail[1].split(',');				// split cart detail 1 (cost options selected) into costoption table
			costarg=cartdetail[2].split(',');					// split cart detail 2 (cost arguments, e.g. qty) into costarg table
			DBobj=fetchDBobj(cartdetail[0]);					// cart detail 0 is the database key - fetch the database object
			costitem=DBobj.cost.split('|');						// split the database cost info into the costitem table
			if (DBobj.entrytype.toLowerCase()!='y') continue;
			awynp=true;
			if (firstline) {
				firstline=false;
				document.write('<tr><td align="left" valign="top">');
				document.write('<span class="largertxtbold">&bull; Space has been reserved in the following Young Naturalist Programs:</span><br>');
			}
			document.write('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+costarg[0]);
			if (cartdetail[1]==1) document.write(' participant, ');
			if (cartdetail[1]>1) document.write(' participants, ');
			document.write(DBobj.mmddyy+', <em>'+DBobj.title+'</em>, on '+DBobj.island+' Island, '+'<br>');
		}
		if (!firstline) document.write('</td></tr>');
		/* if adult workshops or young naturalist programs have been reserved, output the standard disclaimers */
		if (awynp) {
				document.write('<tr><td align="left" valign="top"><br>');
				document.write('<p align="center" class="smallertxtbold" style="margin:0px 50px 0px 50px;padding:4px;border:1px solid #336633">');
				document.write('This receipt confirms your reservation(s) in the above workshops or programs.<br>');
				document.write('Your space is secured upon receipt of your tuition payment.<br>');
				document.write('<span class="redtext">-- Tuition is non-refundable --</span></p><br>');
				document.write('<p align="justify" class="smallertxtbold" style="margin:0px 35px 0px 35px;padding:4;border:1px solid #336633">');
				document.write('Weather conditions can and do vary during the day in the islands, so it is important ');
				document.write('to come prepared. Please be sure to bring the following: clothing appropriate for the weather ');
				document.write('conditions, comfortable walking shoes, brown bag lunch for those courses that cover the ');
				document.write('lunch hour. The following items are optional: binoculars for watching wildlife, paper and  ');
				document.write('pens for field notes, bottled water. There may be no place for you to store personal ');
				document.write('items, so please be prepared to carry whatever you bring throughout the class.</p><br>');
				document.write('</td></tr>');
		}
	}

