
// Error handler for the asynchronous functions.
var myErrorHandler = function(statusCode, statusMsg) {
	alert('Status: ' + statusCode + ', ' + statusMsg);
}

// Hides errors produced by asynchronous functions.
var SuppressError = function(statusCode, statusMsg) {
	// Do nothing
}

var IsNumeric = function(strString) {
   var strValidChars = "0123456789";
   var strChar;
   var blnResult = true;

   if (strString.length == 0) return false;

   //  test strString consists of valid characters listed above
   for (var i = 0; i < strString.length && blnResult == true; i++) {
      strChar = strString.charAt(i);
      if (strValidChars.indexOf(strChar) == -1) {
         blnResult = false;
      }
   }
   return blnResult;
}

var IsFloat = function(strString) {
   var strValidChars = "0123456789.";
   var strChar;
   var blnResult = true;
   var DecimalCnt = 0;

   if (strString.length == 0) return false;

   //  test strString consists of valid characters listed above
   for (var i = 0; i < strString.length && blnResult == true; i++) {
      strChar = strString.charAt(i);
      if (strValidChars.indexOf(strChar) == -1) {
         blnResult = false;
      }
	  // Keep track of how many decimal points we find
	  if (strChar=='.') {
		  DecimalCnt++;
	  }
   }
   
   // Make sure we didn't find more than one decimal point
   if (DecimalCnt > 1)
     blnResult = false;
	 
   return blnResult;
}

// Given a string representation of what is supposed to be a float value, returns the same string with any commas removed
var CleanFloatStr = function(strString) {
   var strChar;
   var Result = '';

   if (strString.length == 0) 
     return '';

   //  Loop through strString
   for (var i = 0; i < strString.length; i++) {
      strChar = strString.charAt(i);
      if (strChar!=',') {
         Result = Result + strChar;
      }
   }
   
   return Result;
}

var CurrencyFormat = function(num) {
	var sign, cents;
	
	num = num.toString().replace(/\$|\,/g,'');
	if(isNaN(num))
		num = "0";
	sign = (num == (num = Math.abs(num)));
	num = Math.floor(num*100+0.50000000001);
	cents = num%100;
	num = Math.floor(num/100).toString();
	if(cents < 10)
		cents = "0" + cents;
	for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++)
		num = num.substring(0,num.length-(4*i+3))+','+
		num.substring(num.length-(4*i+3));
	return (((sign)?'':'-') + num + '.' + cents);
}

var Left = function(str, n){
	if (n <= 0)
	    return "";
	else if (n > String(str).length)
	    return str;
	else
	    return String(str).substring(0,n);
}

var Right = function(str, n){
    if (n <= 0)
       return "";
    else if (n > String(str).length)
       return str;
    else {
       var iLen = String(str).length;
       return String(str).substring(iLen, iLen - n);
    }
}

// Trims a string
var Trim = function(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}

// Removes an arbitrary element by id
var removeEl = function(idEl){
	var t = document.getElementById(idEl);
	t.parentNode.removeChild(t);
}

// Removes a row from a table by using ids
var removeRowByIDs = function(idTable, idRow){
	var table = document.getElementById(idTable);
	var row = document.getElementById(idRow);
	var tbody = table.getElementsByTagName("tbody")[0];
	
	tbody.removeChild(row);
}

var MM_openBrWindow = function(theURL,winName,features){ 
  window.open(theURL,winName,features);
}

var MM_displayStatusMsg = function(msgStr) { 
  status=msgStr;
  document.MM_returnValue = true;
}

var MM_callJS = function(jsStr) { 
  return eval(jsStr);
}

var GoToLoginPage = function(){
	window.location.href = 'index.cfm';
}

var getSelectedRadio = function(buttonGroup) {
   // returns the array number of the selected radio button or -1 if no button is selected
   if (buttonGroup[0]) { // if the button group is an array (one button is not an array)
      for (var i=0; i<buttonGroup.length; i++) {
         if (buttonGroup[i].checked) {
            return i
         }
      }
   } else {
      if (buttonGroup.checked) { return 0; } // if the one button is checked, return zero
   }
   // if we get to this point, no radio button is selected
   return -1;
} // Ends the "getSelectedRadio" function

var getSelectedRadioValue = function(buttonGroup) {
   // returns the value of the selected radio button or "" if no button is selected
   var i = getSelectedRadio(buttonGroup);
   if (i == -1) {
      return "";
   } else {
      if (buttonGroup[i]) { // Make sure the button group is an array (not just one button)
         return buttonGroup[i].value;
      } else { // The button group is just the one button, and it is checked
         return buttonGroup.value;
      }
   }
} // Ends the "getSelectedRadioValue" function

// Selects the specified option value in the select list
var SetSelectOption = function(selectID, optionValue){
	var list = document.getElementById(selectID);
	for (var intI = 0; intI < list.options.length; intI++) {
	  if (list.options[intI].value == optionValue) {
		list.options[intI].selected = true;
	  }
	}
}

// Changes the specified option text and value in the select list
var ChangeSelectOption = function(selectID, optionValueOld, optionTextNew, optionValueNew){
	var list = document.getElementById(selectID);
	for (var intI = 0; intI < list.options.length; intI++) {
	  if (list.options[intI].value == optionValueOld) {
		list.options[intI].text = optionTextNew;
		list.options[intI].value = optionValueNew;
	  }
	}
}

var errors='';

function MM_validateForm() { //v4.0
  if (document.getElementById){
    var i,p,q,nm,test,num,min,max,args=MM_validateForm.arguments;
    for (i=0; i<(args.length-2); i+=3) { test=args[i+2]; val=document.getElementById(args[i]);
      if (val) { nm=val.name; if ((val=val.value)!="") {
        if (test.indexOf('isEmail')!=-1) { p=val.indexOf('@');
          if (p<1 || p==(val.length-1)) errors+='- '+nm+' must contain an e-mail address.\n';
        } else if (test!='R') { num = parseFloat(val);
          if (isNaN(val)) errors+='- '+nm+' must contain a number.\n';
          if (test.indexOf('inRange') != -1) { p=test.indexOf(':');
            min=test.substring(8,p); max=test.substring(p+1);
            if (num<min || max<num) errors+='- '+nm+' must contain a number between '+min+' and '+max+'.\n';
      } } } else if (test.charAt(0) == 'R') errors += '- '+nm+' is required.\n'; }
    } if (errors) alert('The following error(s) occurred:\n'+errors);
    document.MM_returnValue = (errors == '');
} }

var SetAllCheckBoxes = function(FormName, FieldName, CheckValue){
	if(!document.forms[FormName])
		return;
	var objCheckBoxes = document.forms[FormName].elements[FieldName];
	if(!objCheckBoxes)
		return;
	var countCheckBoxes = objCheckBoxes.length;
	if(!countCheckBoxes)
		objCheckBoxes.checked = CheckValue;
	else
		// set the check value for all check boxes
		for(var i = 0; i < countCheckBoxes; i++)
			objCheckBoxes[i].checked = CheckValue;
}

var MenuShowing = true;

var ToggleMenuDisplay = function() {
	var LeftMenu = document.getElementById('LeftMenu');
	var ShowHideArrow = document.getElementById('ShowHideArrow');
	
	if (MenuShowing) {
		LeftMenu.style.display = 'none';
		ShowHideArrow.src = 'images/expand.gif';
		MenuShowing = false;
	} else {
		LeftMenu.style.display = '';
		ShowHideArrow.src = 'images/collapse.gif';
		MenuShowing = true;
	}
}

// Find the x position of an object
function myFindPosX(obj) {
	var curleft = 0;
	if(obj.offsetParent)
		while(1) 
		{
		  curleft += obj.offsetLeft;
		  if(!obj.offsetParent)
			break;
		  obj = obj.offsetParent;
		}
	else if(obj.x)
		curleft += obj.x;
	return curleft;
}

// Find the y position of an object
function myFindPosY(obj) {
	var curtop = 0;
	if(obj.offsetParent)
		while(1)
		{
		  curtop += obj.offsetTop;
		  if(!obj.offsetParent)
			break;
		  obj = obj.offsetParent;
		}
	else if(obj.y)
		curtop += obj.y;
	return curtop;
}

function FindPosById(idCtrl) { 
	var pos = {x:0, y:0};
	var ctrl = document.getElementById(idCtrl);
	
	if (ctrl.offsetParent) {
		while(ctrl) {
			pos.x += ctrl.offsetLeft;
			pos.y += ctrl.offsetTop;
			ctrl = ctrl.offsetParent;
		}
	} else if (ctrl.x && ctrl.y) {
		pos.x += ctrl.x;
		pos.y += ctrl.y;
	}
	
	return pos;
}

function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

// Find the x position of an object
function findPosX(obj) {
	var curleft = 0;
	if(obj.offsetParent)
		while(1) 
		{
		  curleft += obj.offsetLeft;
		  if(!obj.offsetParent)
			break;
		  obj = obj.offsetParent;
		}
	else if(obj.x)
		curleft += obj.x;
	return curleft;
}

// Find the y position of an object
function findPosY(obj) {
	var curtop = 0;
	if(obj.offsetParent)
		while(1)
		{
		  curtop += obj.offsetTop;
		  if(!obj.offsetParent)
			break;
		  obj = obj.offsetParent;
		}
	else if(obj.y)
		curtop += obj.y;
	return curtop;
}

// Moves an absolutely positioned object to a position relative to another object
function relPosition(moveID, relID, dX, dY, SubtractWidth) {
	var moveObj = MM_findObj(moveID);
	var relObj = MM_findObj(relID);
	var relObjX = findPosX(relObj);
	var relObjY = findPosY(relObj);
	// Move the obj left it's own width
	if (SubtractWidth) {
		// Show the obj - need to do this first to get it's width
		moveObj.style.display = '';
		// Move the obj
		moveObj.style.left = (relObjX + dX - moveObj.offsetWidth) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
	} else {
		// Move the obj
		moveObj.style.left = (relObjX + dX) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
		// Show the obj
		moveObj.style.display = '';
	}
	
}

// Moves an absolutely positioned object to a position relative to another object, but based on object
function relPositionObj(moveID, relObj, dX, dY, SubtractWidth) {
	var moveObj = MM_findObj(moveID);
	var relObjX = myFindPosX(relObj);
	var relObjY = myFindPosY(relObj);
	
	// Move the obj left it's own width
	if (SubtractWidth) {
		// Show the obj - need to do this first to get it's width
		moveObj.style.display = '';
		// Move the obj
		moveObj.style.left = (relObjX + dX - moveObj.offsetWidth) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
	} else {
		// Move the obj
		moveObj.style.left = (relObjX + dX) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
		// Show the obj
		moveObj.style.display = '';
	}
	
}

// Moves an absolutely positioned object to a position relative to another object, but based on object
// This version uses JQuery to get the coordinates of the relObj because JQuery's function to do that
// supports the object being in a scrolling div container
function relPositionObjJQ(moveID, relObj, dX, dY, SubtractWidth) {
	var moveObj = MM_findObj(moveID);
	var relObjPos = $(relObj).offset();
	var relObjX = relObjPos.left;
	var relObjY = relObjPos.top;
	
	// Move the obj left it's own width
	if (SubtractWidth) {
		// Show the obj - need to do this first to get it's width
		moveObj.style.display = '';
		// Move the obj
		moveObj.style.left = (relObjX + dX - moveObj.offsetWidth) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
	} else {
		// Move the obj
		moveObj.style.left = (relObjX + dX) + 'px';
		moveObj.style.top = (relObjY + dY) + 'px';
		// Show the obj
		moveObj.style.display = '';
	}
	
}

function getCursorXY(e) {
	var x = (window.Event) ? e.pageX : event.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
	var y = (window.Event) ? e.pageY : event.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
	return [x,y];
}

/*
   name - name of the cookie
   value - value of the cookie
   [expires] - expiration date of the cookie
     (defaults to end of current session)
   [path] - path for which the cookie is valid
     (defaults to path of calling document)
   [domain] - domain for which the cookie is valid
     (defaults to domain of calling document)
   [secure] - Boolean value indicating if the cookie transmission requires
     a secure transmission
   * an argument defaults when it is assigned null as a placeholder
   * a null placeholder is not required for trailing omitted arguments
*/

function setCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}

/*
  name - name of the desired cookie
  return string containing value of specified cookie or null
  if cookie does not exist
*/

function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

var SubmitOnEnter = function(myfield,e) {
	var keycode;
	if (window.event) 
		keycode = window.event.keyCode;
	else 
		if (e) 
			keycode = e.which;
	else 
		return true;
	
	if (keycode == 13) {
	   myfield.form.Submit.click();
	   return false;
	} else
	   return true;
}

// Used like this: <input type=text onkeyup="getKey(event, 13, 'myjsfunc();')">
var getKey = function(e, keyCode, jscode) {
	if(e.keyCode == keyCode) {
		eval(jscode);
	}
}

var SortListBox = function(id) {
  var box = document.getElementById(id);
  var tmp  = new Array();
  var len = box.options.length;
  for (i = 0; i < len; i++) {
    tmp[i] = new Array(box.options[i].text.toLowerCase(), new Object(box.options[i]));
  }
  tmp.sort();

  box.options.length = 0;

  for (i = 0; i < len; i++) box.options.add(tmp[i][1]);
}

var MoveListItem = function(idSource, idTarget) {
	var Source = document.getElementById(idSource);
	var Target = document.getElementById(idTarget);

	if ((Source != null) && (Target != null)) {
		while ( Source.options.selectedIndex >= 0 ) {
			var newOption = new Option(); // Create a new instance of ListItem
			newOption.text = Source.options[Source.options.selectedIndex].text;
			newOption.value = Source.options[Source.options.selectedIndex].value;
		   
			Target.options[Target.length] = newOption; //Append the item in Target
			Source.remove(Source.options.selectedIndex);  //Remove the item from Source
		}
	}
	
	SortListBox(idTarget);
}

var selectAllListOptions = function(idSelect) {
	var ref = document.getElementById(idSelect);
	
	for(var i=0; i < ref.options.length; i++)
		ref.options[i].selected = true;
}

var GoToURL = function(URL){
	window.location.href = URL;
}

var OverCallout = false;
var HideCalloutTimer;
var idTblCallout = 'tblCallout';
var arrCalloutsToHide = new Array();

// Adds a callout id to the array of callouts to hide, but only if it isn't already in the array
var AddCalloutIdToArray = function(idCallout){
	var posCalloutId = -1;
	//Check to see if the callout id is already in the array
	for(var i=0; i < arrCalloutsToHide.length; i++)
		if (arrCalloutsToHide[i] == idCallout)
			posCalloutId = i;
	// If it's not already in the array, add it
	arrCalloutsToHide.splice(0,0,idCallout);
}

// Removes a callout id from the array of callouts to hide
var RemoveCalloutIdFromArray = function(idCallout){
	var posCalloutId = -1;
	//Find the callout id in the array of callouts that are showing
	for(var i=0; i < arrCalloutsToHide.length; i++)
		if (arrCalloutsToHide[i] == idCallout)
			posCalloutId = i;
	// Remove the callout id from the array
	if (posCalloutId > -1)
		arrCalloutsToHide.splice(posCalloutId,1);
}

var OnMouseOverCallout = function(idCallout){
	//if (HideCalloutTimer)
		//clearTimeout(HideCalloutTimer);
	// Add the callout id to the array of callouts that are showing
	//AddCalloutIdToArray(idCallout);
	
	// Remove the callout id from the array of callouts to hide, if it is in the list
	RemoveCalloutIdFromArray(idCallout);
	// Set the flag that the mouse is over the callout
	OverCallout = true;
}

var OnMouseOutCallout = function(idCallout){
	// Hide the callout
	// HideCallout(idCallout);
	// If no callouts are showing, clear the OverCallout flag
	//if (arrCallouts.length == 0)
		//OverCallout = false;
		
	// Set the flag that the mouse is not over the callout
	OverCallout = false;
	// Set the hide callout timer
	SetHideCallout(idCallout);
}

var ShowCallout = function(Desc, idPos) {
	//if (HideCalloutTimer)
		//clearTimeout(HideCalloutTimer);
	idTblCallout = 'tblCallout';
	var CalloutDescTD = document.getElementById('tdCalloutDesc');

	if (CalloutDescTD) {
		// Put the description in place
		CalloutDescTD.innerHTML = Desc;
		// Move the layer
		relPosition(idTblCallout, idPos, 5, -10, true);
	}
}

var ShowCalloutObj = function(Desc, objPos, dX, dY, CallOutWidth) {
	if (HideCalloutTimer){
		clearTimeout(HideCalloutTimer);
		HideCalloutTimer = null;
	}
	var CalloutDescTD = document.getElementById('tdCalloutDesc');
	
	if (CalloutDescTD) {
		// If we have a width value and it's greater than 0, set the width
		if (CallOutWidth && CallOutWidth > 0)
			CalloutDescTD.style.width = CallOutWidth + 'px';
		// Put the description in place
		CalloutDescTD.innerHTML = Desc;
		// Move the layer
		relPositionObj(idTblCallout, objPos, dX, dY, true);
	}
}

var ShowFeaItemCalloutObj = function(idFeaItemCallout, objPos, dX, dY, CallOutWidth) {
	//if (HideCalloutTimer)
		//clearTimeout(HideCalloutTimer);
	idTblCallout = idFeaItemCallout;
	// Remove the callout id from the array of callouts to hide, if it is in the list
	RemoveCalloutIdFromArray(idTblCallout);
	relPositionObj(idTblCallout, objPos, dX, dY, true);
}

var ShowRecommProdCalloutObj = function(idRecommProdCallout, objPos, dX, dY, CallOutWidth) {
	//if (HideCalloutTimer)
		//clearTimeout(HideCalloutTimer);
	idTblCallout = idRecommProdCallout;
	// Remove the callout id from the array of callouts to hide, if it is in the list
	RemoveCalloutIdFromArray(idTblCallout);
	relPositionObjJQ(idTblCallout, objPos, dX, dY, false);
}

var HideCallout = function() {
	// Loop through the array of callouts to hide
	for(var i=0; i < arrCalloutsToHide.length; i++){
		if (document.getElementById(arrCalloutsToHide[i])) {
			// Hide the callout
			document.getElementById(arrCalloutsToHide[i]).style.display='none';
			// Remove the callout id from the array of callouts to hide
			RemoveCalloutIdFromArray(arrCalloutsToHide[i]);
		}
	}
}

var SetHideCallout = function(idCallout) {
	// Add the callout id to the array of callouts to hide
	AddCalloutIdToArray(idCallout);
	HideCalloutTimer = setTimeout(HideCallout, 100);
}

var returnDocument = function() {
	var file_name = document.location.href;
	var end = (file_name.indexOf("?") == -1) ? file_name.length : file_name.indexOf("?");
	return file_name.substring(file_name.lastIndexOf("/")+1, end);
}

var DHTMLSound = function(idAudioSpan, surl) {
  document.getElementById(idAudioSpan).innerHTML=
    "<embed src='"+surl+"' hidden=true autostart=true loop=false>";
}

// Scrolls the contents of a div up
var ScrollUp = function() {
	document.getElementById(ScrollUpDivID).scrollTop -= 10;
}
  
// Scrolls the contents of a div down
var ScrollDn = function() {
	document.getElementById(ScrollDnDivID).scrollTop += 10;
}

// Starts repeated scrolling up - generally called in onmousedown
var StartScrollUp = function(idDiv){
	// Purposely not a var so it's global
	ScrollUpDivID = idDiv;
	ScrollUp();
	ScrollUpTimeout = setInterval(ScrollUp,50);
}

// Stops repeated scrolling up - generally called in onmouseup
var StopScrollUp = function(){
	if (typeof(ScrollUpTimeout) != "undefined") clearTimeout(ScrollUpTimeout);
}

// Starts repeated scrolling down - generally called in onmousedown
var StartScrollDn = function(idDiv){
	// Purposely not a var so it's global
	ScrollDnDivID = idDiv;
	ScrollDn();
	ScrollDnTimeout = setInterval(ScrollDn,50);
}

// Stops repeated scrolling down - generally called in onmouseup
var StopScrollDn = function(){
	if (typeof(ScrollDnTimeout) != "undefined") clearTimeout(ScrollDnTimeout);
}

var callback = function(text){
	//alert("Callback: " + text);
}



// Auto-clears the Email field in the login form
var LoginFormEmailOnFocus = function(objFld){
	if (objFld.value == 'Email address')
		objFld.value = '';
}

// "Auto-clears" the Password field in the login form - it actually swaps between a 
// fake and real password field so everything will work properly in IE
var LoginFormFakeOnFocus = function(objFld){
	if (objFld.value == 'Password') {
		objFld.style.display = 'none';
		document.LoginForm.LoginPassword.style.display = '';
		document.LoginForm.LoginPassword.focus();
	}
}

// Displays a semester's subjects
var ToggleSemSubjs = function(SemesterID){
	var TheDiv = document.getElementById('Sem' + SemesterID + 'Subjs');
	var CurrDisplayVal = TheDiv.style.display;
	
	if (CurrDisplayVal == '')
		TheDiv.style.display = 'none';
	else
		TheDiv.style.display = '';
}

// Displays a subject's courses
var ToggleSubjCourses = function(SemSubjID){
	var TheDiv = document.getElementById('Subj' + SemSubjID + 'Courses');
	var CurrDisplayVal = TheDiv.style.display;
	
	if (CurrDisplayVal == '')
		TheDiv.style.display = 'none';
	else
		TheDiv.style.display = '';
}

// Redirects to a page that shows the products for the specified semester/subject/course  
var GoToSemSubjCourse = function(SemesterID,SemSubjID,CourseID){
	window.location.href = 'school_prods.cfm?semester_id=' + SemesterID + '&semsubj_id=' + SemSubjID + '&course_id=' + CourseID;
}

// Redirects to a page that shows the products for the specified semester/subject  
var GoToSemSubj = function(SemesterID,SemSubjID){
	window.location.href = 'school_prods.cfm?semester_id=' + SemesterID + '&semsubj_id=' + SemSubjID;
}

// Refreshes the cart (backpack) item count
var RefreshCartItemCnt = function(){
	// Save the CF Loading... message HTML
	var Orig_cf_loadingtexthtml = _cf_loadingtexthtml="";
	
	// Temporarily clear the CF Loading... message HTML
	_cf_loadingtexthtml="";
	// URL version of calling the CFC binding
	ColdFusion.navigate('CartRemote.cfc?method=GetCartItemCntStr','divCartItemCnt');
	// Restore the CF Loading... message HTML
	_cf_loadingtexthtml = Orig_cf_loadingtexthtml;
}

// Refreshes the cart (backpack) subtotal
var RefreshCartSubtotal = function(){
	// Save the CF Loading... message HTML
	var Orig_cf_loadingtexthtml = _cf_loadingtexthtml="";
	
	// Temporarily clear the CF Loading... message HTML
	_cf_loadingtexthtml="";
	// URL version of calling the CFC binding
	ColdFusion.navigate('CartRemote.cfc?method=GetCartSubtotalStr','divCartSubtotal');
	// Restore the CF Loading... message HTML
	_cf_loadingtexthtml = Orig_cf_loadingtexthtml;
}

var LoginWarningWindowOnHide = function(){
	// Destroy the PO window
	ColdFusion.Window.destroy('LoginWarningWindow', true);
}

var AFeaItemSectProdID = '';

// Add items to the cart
var AddToCart = function(CustID,ProdID,SemSubjID,CourseID,FeaItemSectProdID){
	if (!FeaItemSectProdID)
		FeaItemSectProdID = '';
	AFeaItemSectProdID = FeaItemSectProdID;
	// Default for new qty
	var QtyNew = 0;
	// Default for used qty
	var QtyUsed = 0;
	// Default for rental qty
	var QtyRental = 0;
	var RentPerID = 0;
	var CartItemAttribs = '';
	
	// Get the qty of new product the user wants, if such a field exists
	var objQtyNew = document.getElementById('QtyNew' + SemSubjID + CourseID + ProdID + FeaItemSectProdID);
	if (objQtyNew)
		QtyNew = objQtyNew.value;
	
	// Get the qty of used product the user wants, if such a field exists
	var objQtyUsed = document.getElementById('QtyUsed' + SemSubjID + CourseID + ProdID + FeaItemSectProdID);
	if (objQtyUsed)
		QtyUsed = objQtyUsed.value;
	
	// Get the qty of product the user wants to rent, if such a field exists
	var objQtyRental = document.getElementById('QtyRental' + SemSubjID + CourseID + ProdID + FeaItemSectProdID);
	if (objQtyRental) {
		QtyRental = objQtyRental.value;
		if (IsNumeric(QtyRental) && QtyRental > 0) {
			// Get the rental period ID
			var objRentPerIDPrice = document.getElementById('RentalPer' + SemSubjID + CourseID + ProdID + FeaItemSectProdID);
			var RentPerIDPrice = objRentPerIDPrice[objRentPerIDPrice.selectedIndex].value;
			var arrRentPerIDPrice = RentPerIDPrice.split('|');
			RentPerID = arrRentPerIDPrice[0];
		}
	}
	
	// Only logged-in customers can add to the cart
	if (CustID > 0) {

		if (IsNumeric(QtyNew) && QtyNew > 0) {
			// Clear the Qty field
			objQtyNew.value = '';
			
			// Get any attributes
			var ProdAttribTypeIDList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_IDList.value');
			
			if (ProdAttribTypeIDList != '') {
				var AttribType = '';
				var AttribValue = '';
				var AttribCtrl = '';
				var objAttribCtrl;
				var ProdAttribTypeTypeList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_TypeList.value');
				var ProdAttribDefValueList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.ProdAttribDefValueList.value');
				var arrProdAttribTypeIDList = ProdAttribTypeIDList.split(',');
				var arrProdAttribTypeTypeList = ProdAttribTypeTypeList.split(',');
				var arrProdAttribDefValueList = ProdAttribDefValueList.split(',');
				// Loop through the attributes and assemble the CartItemAttribs string, which is encoded as a comma-separated list of 
				// PRODATTRIBTYPE_ID|PRODATTRIBTYPE_Type|AttribValue, where AttribValue is PRODATTRIBSELOPT_ID, PRODATTRIB_YesNoValue, or a free-form value
				// depending upon the attribute type
				for (var i = 0; i < arrProdAttribTypeIDList.length; i++) {
					// Get the attribute type
					AttribType = arrProdAttribTypeTypeList[i];
					// Get the attribute form control object
					AttribCtrl = 'document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_ID' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + arrProdAttribTypeIDList[i];
					objAttribCtrl = eval(AttribCtrl);
					
					// Get the attribute value - how you do that varies by attribute type
					if (AttribType == 'S'){
						// Do we have a hidden field from an image select?
						if (objAttribCtrl.type == 'hidden') {
							AttribValue = objAttribCtrl.value;
						// Regular select
						} else {
							AttribValue = objAttribCtrl[objAttribCtrl.selectedIndex].value;
						}
					} else if (AttribType == 'Y'){
						AttribValue = getSelectedRadio(objAttribCtrl);
					} else {
						AttribValue = objAttribCtrl.value;
						// Reset the product attribute to it's default
						objAttribCtrl.value = '';
					}
					
					if (CartItemAttribs != '')
						CartItemAttribs = CartItemAttribs + ',';
						
					// Add the attribute info to the cart item attributes string
					CartItemAttribs = CartItemAttribs + arrProdAttribTypeIDList[i] + '|' + AttribType + '|' + AttribValue;
					
				}
			}

			// create an instance of the proxy. 
			var e = new CartRemote();
			e.setCallbackHandler(AddToCartResult);
			e.setErrorHandler(myErrorHandler);
			e.AddCartItem(ProdID,SemSubjID,CourseID,'N',QtyNew,'S',0,CartItemAttribs);
		}
	
		if (IsNumeric(QtyUsed) && QtyUsed > 0) {
			// Clear the Qty field
			objQtyUsed.value = '';
			// create an instance of the proxy. 
			var e = new CartRemote();
			e.setCallbackHandler(AddToCartResult);
			e.setErrorHandler(myErrorHandler);
			e.AddCartItem(ProdID,SemSubjID,CourseID,'U',QtyUsed,'S');
		}
	
		if (IsNumeric(QtyRental) && QtyRental > 0) {
			// Clear the Qty field
			objQtyRental.value = '';
			// create an instance of the proxy. 
			var e = new CartRemote();
			e.setCallbackHandler(AddToCartResult);
			e.setErrorHandler(myErrorHandler);
			// Rentals are added to the cart as new items, and potentially later split and changed to used if that is available
			e.AddCartItem(ProdID,SemSubjID,CourseID,'N',QtyRental,'R',RentPerID);
		}
	
	} else {

		if (IsNumeric(QtyNew) && QtyNew > 0) {
			var ProdAttribTypeIDList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_IDList.value');
			
			if (ProdAttribTypeIDList != '') {
				var AttribType = '';
				var AttribValue = '';
				var AttribCtrl = '';
				var objAttribCtrl;
				var ProdAttribTypeTypeList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_TypeList.value');
				var ProdAttribDefValueList = eval('document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.ProdAttribDefValueList.value');
				var arrProdAttribTypeIDList = ProdAttribTypeIDList.split(',');
				var arrProdAttribTypeTypeList = ProdAttribTypeTypeList.split(',');
				var arrProdAttribDefValueList = ProdAttribDefValueList.split(',');
				// Loop through the attributes and assemble the CartItemAttribs string, which is encoded as a comma-separated list of 
				// PRODATTRIBTYPE_ID|PRODATTRIBTYPE_Type|AttribValue, where AttribValue is PRODATTRIBSELOPT_ID, PRODATTRIB_YesNoValue, or a free-form value
				// depending upon the attribute type
				for (var i = 0; i < arrProdAttribTypeIDList.length; i++) {
					// Get the attribute type
					AttribType = arrProdAttribTypeTypeList[i];
					// Get the attribute form control object
					AttribCtrl = 'document.Add' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + '.PRODATTRIBTYPE_ID' + SemSubjID + CourseID + ProdID + FeaItemSectProdID + arrProdAttribTypeIDList[i];
					objAttribCtrl = eval(AttribCtrl);
					
					// Get the attribute value - how you do that varies by attribute type
					if (AttribType == 'S'){
						// Do we have a hidden field from an image select?
						if (objAttribCtrl.type == 'hidden') {
							AttribValue = objAttribCtrl.value;
						// Regular select
						} else {
							AttribValue = objAttribCtrl[objAttribCtrl.selectedIndex].value;
						}
					} else if (AttribType == 'Y'){
						AttribValue = getSelectedRadio(objAttribCtrl);
					} else {
						AttribValue = objAttribCtrl.value;
						// Reset the product attribute to it's default
						objAttribCtrl.value = '';
					}
					
					// Special separator (^ rather than ,) because the attribute list will be combined with another comma-separated pipe-delimited list
					if (CartItemAttribs != '')
						CartItemAttribs = CartItemAttribs + '^';
						
					// Add the attribute info to the cart item attributes string - 
					// Special separator (~ rather than |) because the attribute list will be combined with another comma-separated pipe-delimited list
					CartItemAttribs = CartItemAttribs + arrProdAttribTypeIDList[i] + '~' + AttribType + '~' + AttribValue;
					
				}
			}
		}

		ColdFusion.Window.create('LoginWarningWindow', 'Account/Login Required', 
			'acct_login_req_warning.cfm?prod_id=' + ProdID + '&semsubj_id=' + SemSubjID + '&course_id=' + CourseID + '&qtynew=' + QtyNew + '&qtyused=' + QtyUsed + '&qtyrental=' + QtyRental + '&rentper_id=' + RentPerID + '&CartItemAttribs=' + CartItemAttribs,
			{x:100,y:100,height:190,width:400,modal:true,closable:true,
			draggable:true,resizable:false,center:true,initshow:true,
			refreshonshow:true,bodystyle:'color:#000000; background-color:#ffffff; padding: 5px;'});
		document.getElementById('LoginWarningWindow_title').className = 'cfWindowTitleBar';
		ColdFusion.Window.onHide('LoginWarningWindow', LoginWarningWindowOnHide);
	
	}
}

var HideAddedToBackpack = function(){
	document.getElementById('AddedToBackpack').style.display = 'none';
}

// Res is a structure containing the number-of-items-in-the-cart string (so we can update the cart display with it), an error message, and some of the original values
var AddToCartResult = function(Res){
	// Only stop/play the add to cart sound if there wasn't an error druing the add to cart
	if (Res.ERRORMSG == '') {
		// Stop any sound that might be playing
		//StopSound('AddToCartWav');
		// Play a sound to give some indication that the item was added to the cart
		//PlaySound('AddToCartWav', 'media/kerchunk.wav');
		DHTMLSound('AddToCartWav', 'media/kerchunk.wav')
		relPosition('AddedToBackpack','AddBtn' + Res.SEMSUBJ_ID + Res.COURSE_ID + Res.PROD_ID + AFeaItemSectProdID,95,2,false);
		// Hide the "added to backpack" indicator in 1 second
		setTimeout('HideAddedToBackpack()',1000);
	}
	// Update the cart item count
	document.getElementById('divCartItemCnt').innerHTML = Res.ITEMCNTSTR;
	// Update the cart subtotal
	RefreshCartSubtotal();
	// If there is a non-zero NetAvailUsedInv returned, display it as the used qty value
	//if (Res.NETAVAILUSEDINV > 0)
		//document.getElementById('QtyUsed' + Res.SEMSUBJ_ID + Res.COURSE_ID + Res.PROD_ID).value = Res.NETAVAILUSEDINV;
	// Show any error
	if (Res.ERRORMSG != '')
		alert(Res.ERRORMSG);
		
	// Get the current page file name
	var CurrDocument = returnDocument();
	
	// If we're on the backpack page or any of the subsequent pages in the checkout process, goto/refresh the backpack page.
	// However, we do not do that for the recommended items page because the user may want to add multiple items to their
	// backpack from that page. See the next code block for special handling of that page.
	if (CurrDocument == 'backpack.cfm' || 
		CurrDocument == 'checkout1.cfm' || 
		CurrDocument == 'checkout2.cfm' || 
		CurrDocument == 'checkout3.cfm' || 
		CurrDocument == 'checkout3a.cfm' || 
		CurrDocument == 'checkout4.cfm' || 
		CurrDocument == 'checkout5.cfm')
		GoToURL('backpack.cfm');
		
	// If we're on the recommended items page and just added the first rental item to the backpack,
	// send the customer back to the backpack page so they can accept the rental agreement
	if (CurrDocument == 'recomm_items.cfm' && Res.RENTALCNTBEFORE == 0 && Res.RENTALCNTAFTER > 0)
	  GoToURL('backpack.cfm');
	  
	// If we're on the recommended items page and didn't get redirected above, then just refresh the recommended items
	// page so the item that was just added to the cart will disappear
	if (CurrDocument == 'recomm_items.cfm')
	  GoToURL('recomm_items.cfm');
}

// OnHide for VBSMismatch
var VBSMismatchWindowOnHide = function(){
	ColdFusion.Window.destroy('VBSMismatchWindow', true)
}

// Handle a click on the Deal link next to a quote in the list on cust_detail_trans_doclist.cfm page
var VBSMismatch = function(){
	ColdFusion.Window.create('VBSMismatchWindow', 'School Bookstore Mismatch', 'vbsmismatch.cfm',
						{x:100,y:100,height:100,width:380,modal:true,closable:true,
						draggable:true,resizable:false,center:true,initshow:true,
						refreshonshow:true,bodystyle:'color:#000000; background-color:#ffffff; padding: 5px;'});
	document.getElementById('VBSMismatchWindow_title').className = 'cfWindowTitleBar';
	ColdFusion.Window.onHide('VBSMismatchWindow', VBSMismatchWindowOnHide);
}

// Not used
var onErrorClearField = function(form, ctrlName, value, message) {
	alert(message);
	document.getElementById(ctrlName).value = '';
	document.getElementById(ctrlName).focus();
   }

// OnHide for BTSALackOfPurchWarning
var BTSALackOfPurchWarningWindowOnHide = function(){
	ColdFusion.Window.destroy('BTSALackOfPurchWarningWindow', true)
}

// Display a BTSA product group lack of purchase warning
var BTSALackOfPurchWarning = function(WarningCopy, RedirectURL){
	ColdFusion.Window.create('BTSALackOfPurchWarningWindow', 'Warning', 'lack_of_purchase_warning.cfm?warningcopy=' + WarningCopy + '&redirecturl=' + RedirectURL,
						{x:100,y:100,height:200,width:400,modal:true,closable:true,
						draggable:true,resizable:false,center:true,initshow:true,
						refreshonshow:true,bodystyle:'color:#000000; background-color:#ffffff; padding: 5px;'});
	document.getElementById('BTSALackOfPurchWarningWindow_title').className = 'cfWindowTitleBar';
	ColdFusion.Window.onHide('BTSALackOfPurchWarningWindow', BTSALackOfPurchWarningWindowOnHide);
}

var SemesterOnChange = function(SemesterID){
	// create an instance of the proxy. 
	var e = new Schools();
	e.setCallbackHandler(SemesterOnChangeResult);
	e.setErrorHandler(myErrorHandler);
	e.GetSubjectCnt(SemesterID);
}

var SemesterOnChangeResult = function(Res){
	if (Res == 1) { 
		document.getElementById('lblSubject').style.display = 'none'; 
		document.CourseSelectForm.SEMSUBJ_ID.style.display = 'none'; 
	} else { 
		document.getElementById('lblSubject').style.display = '';
		document.CourseSelectForm.SEMSUBJ_ID.style.display = ''; 
	}
}
