// JavaScript Document

/*** Global variables. ***/
var xmlHttp;	//For Ajax.

var subjectListArray = new Array('eng', 'chi', 'mth', 'sci', 'mal');
var levelListArray = new Array('n', 'p', 's');	//n: nursery, p: primary, s: secondary.


//Get the number of checkbox selected/checked.
function getNumberCheckboxSelected(chkboxElm)
{
	var cnt = 0;
	
	if (chkboxElm.length == null) //Length is null if there's only 1 element with that name (1 checkbox with that name).
	{
		if (chkboxElm.checked)
			cnt = 1;
		else
			cnt = 0;
	}
	else
	{
		
		for (var i=0; i<chkboxElm.length; i++)
		{
			if (chkboxElm[i].checked)
				 ++cnt;
		}
	}
		
	//alert ("Cntr: " + cnt);
	return cnt;
}


//Function to check or uncheck all checkboxes. Set bCheck true to check all. False to uncheck all.
function checkboxSet(elm, bCheck)
{
	if (elm.length == null) //Length is null if there's only 1 element with that name in the document.
	{
		if (bCheck)
			elm.checked = true;
		else
			elm.checked = false;		
	}
	else
	{
		for (var i=0; i<elm.length; i++)
		{
			if (bCheck)
				elm[i].checked = true;
			else
				elm[i].checked = false;
		}
	}	
}


//AJAX: List accounts for assigning packages.
function listAccountForAssign(evtCnt, sPath)
{	
	//Get the selected filtering element.
	elmListPar = document.getElementById("listpar");
	elmListByChar = document.getElementById("listbychar");
	elmCreateTime = document.getElementById("createtime");
	elmSortBy = document.getElementById("sortby");
	
	//Get the selected filtering data.
	var listPar = elmListPar.options[elmListPar.selectedIndex].value;
	var listByChar = elmListByChar.options[elmListByChar.selectedIndex].value;
	var createTime = elmCreateTime.options[elmCreateTime.selectedIndex].value;
	var sortBy = elmSortBy.options[elmSortBy.selectedIndex].value;
	
	var msg = "";
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX.";
  	}		
	
	if (msg != '')
	{		
		alert(msg);			
		return false;		//Return false if there's error..
	}
	
	var url = sPath + "ajx/listacctforassign.php";
	url = url + "?listpar=" + listPar;
	url = url + "&listbychar=" + listByChar;
	url = url + "&createtime=" + createTime;
	url = url + "&sortby=" + sortBy;
	url = url + "&evtcnt=" + evtCnt;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	var elmAcctList = document.getElementById('acctlist');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
								
			elmAcctList.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//Get the checked radio button value.
function getRadioCheckedValue(radObj)
{	
	if (radObj.length == undefined)
		return radObj.value;
		
	for(var i=0; i<radObj.length; i++)
	{
		if (radObj[i].checked)
			return radObj[i].value;
	}
	
	return "notfound";
}

//Get the selected option value.
function getSelectedOptionValue(selectObj)
{
	var selectedIndex = selectObj.selectedIndex;
	return selectObj.options[selectedIndex].value;
}


//AJAX: List accounts for assigning packages.
function listParentAcctForSelect(elmForm, sPath)
{	
	listPar = getRadioCheckedValue(elmForm["listpar"]);
	listByChar = getRadioCheckedValue(elmForm["listbychar"]);
	createTime = getRadioCheckedValue(elmForm["createtime"]);
	sortBy = getRadioCheckedValue(elmForm["sortby"]);
		
	var msg = "";
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX.";
  	}		
	
	if (msg != '')
	{		
		alert(msg);			
		return false;		//Return false if there's error..
	}
	
	var url = sPath + "ajx/listparacctforselect.php";
	url = url + "?listpar=" + listPar;
	url = url + "&listbychar=" + listByChar;
	url = url + "&createtime=" + createTime;
	url = url + "&sortby=" + sortBy;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	var elmAcctList = document.getElementById('acctlist');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
								
			elmAcctList.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);
}


//Verify entries for creating new event identity.
function checkEventCreate(sID, sName, sDesc, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var id = sID.trim();
	var name = sName.trim();
	var desc = sDesc.trim();
	
	//All fields are compulsory.
	if ( id == "" ||
		 name == "" ||
		 desc == "" )
	{
		errmsg += "\nAll fields are required.";
		result = false;
	}
	
	//Error if User ID not yet checked.
	if (!bChkId)
	{
		errmsg += "\nPlease check whether ID is available for use.";
		result = false;
	}
		
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
}


//AJAX
//Check database if event ID is available for creation.
function checkEventIdty(sId, lenMinId, sPath, elmCkId)
{			
	var msg = '';
	
	if (sId.length < lenMinId)
  	{ 		
		msg = msg + "\ID must be at least " + lenMinId + " characters long."			
  	}
	
	if ( sId.indexOf(" ") != -1 )
  	{ 
		msg = msg + "\ID must not contain space."
  	}
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX.";
  	}
			
	if (msg != '')
	{
		if (elmCkId)
			elmCkId.checked = false;
		
		alert(msg);
			
		return false;		//Return false if there's error..
	}
		
	var url = sPath + "ajx/eventidexistindb.php";
	url = url + "?chkfor=" + sId.toLowerCase();	//All logins in lowercase.
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		return getIdAvailibility(elmCkId);
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//Validate if string is date format: yyyy-mm-dd.
function dateValidate1(sDate)
{
	if ( !isNumeric( sDate.substr(0, 4) ) ||	//Check yyyy.
		 sDate.substr(4, 1) != "-" ||			//Check "-" after yyyy.
		 !isNumeric( sDate.substr(5, 2) ) ||	//Check mm.
		 sDate.substr(7, 1) != "-" ||			//Check "-" after mm.
		 !isNumeric( sDate.substr(8, 2) ) )		//Check dd.
		return false;
	else
		return true;
}


//AJAX: Retrieve secondary login details.
function displaySecLogin(sPath)
{
	var errMsg = "";
	
	var elmEtype = document.getElementById("etype");
	var sEtype = elmEtype.options[elmEtype.selectedIndex].value;
	
	var elmVendor = document.getElementById("vendoridty");
	var sVendor = elmVendor.options[elmVendor.selectedIndex].value;
	
	var elmEvent = document.getElementById("eventidty");
	var sEvent = elmEvent.options[elmEvent.selectedIndex].value;
	
	var sDateFrom = document.getElementById("datefrom").value;	
	var sDateTo = document.getElementById("dateto").value;
		
	if (sEtype == "" || sVendor == "" || sEvent == "" || !dateValidate1(sDateFrom) || !dateValidate1(sDateTo) )
	{
		alert("Please select all required info before listing.");
		return false;
	}
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var elmListSection = document.getElementById('listSection');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
								
			elmListSection.innerHTML = result;
			
			return true;
		}
	}
		
	var url = sPath + "ajx/listsecacct.php";	
	url = url + "?sid=" + Math.random();	//Prevent server sending back cache data.
	
	var params = "etype=" + encodeURIComponent(sEtype);
	params = params + "&vendoridty=" + encodeURIComponent(sVendor);
	params = params + "&eventidty=" + encodeURIComponent(sEvent);
	params = params + "&datefrom=" + encodeURIComponent(sDateFrom);
	params = params + "&dateto=" + encodeURIComponent(sDateTo);
	
	xmlHttp.open("POST", url, true);

	//Send the proper header information along with the request
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", params.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	xmlHttp.send(params);	
}


//Submit form via javascript.
function submitForm(elmForm, sAction)
{	
	elmForm.action= sAction;	//Set form's action.
	elmForm.submit();			//Submit the form.
}


// **** Date Picker >>
var datePickerDivID = "datepicker";
var iFrameDivID = "datepickeriframe";

var dayArrayShort = new Array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
var dayArrayMed = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
var dayArrayLong = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
var monthArrayShort = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
var monthArrayMed = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec');
var monthArrayLong = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
 
// these variables define the date formatting we're expecting and outputting.
// If you want to use a different format by default, change the defaultDateSeparator
// and defaultDateFormat variables either here or on your HTML page.
var defaultDateSeparator = "/";        // common values would be "/" or "."
var defaultDateFormat = "mdy"    // valid values are "mdy", "dmy", and "ymd"
var dateSeparator = defaultDateSeparator;
var dateFormat = defaultDateFormat;

/**
This is the main function you'll call from the onClick event of a button.
Normally, you'll have something like this on your HTML page:

Start Date: <input name="StartDate">
<input type=button value="select" onclick="displayDatePicker('StartDate');">

That will cause the datepicker to be displayed beneath the StartDate field and
any date that is chosen will update the value of that field. If you'd rather have the
datepicker display beneath the button that was clicked, you can code the button
like this:

<input type=button value="select" onclick="displayDatePicker('StartDate', this);">

So, pretty much, the first argument (dateFieldName) is a string representing the
name of the field that will be modified if the user picks a date, and the second
argument (displayBelowThisObject) is optional and represents an actual node
on the HTML document that the datepicker should be displayed below.

In version 1.1 of this code, the dtFormat and dtSep variables were added, allowing
you to use a specific date format or date separator for a given call to this function.
Normally, you'll just want to set these defaults globally with the defaultDateSeparator
and defaultDateFormat variables, but it doesn't hurt anything to add them as optional
parameters here. An example of use is:

<input type=button value="select" onclick="displayDatePicker('StartDate', false, 'dmy', '.');">

This would display the datepicker beneath the StartDate field (because the
displayBelowThisObject parameter was false), and update the StartDate field with
the chosen value of the datepicker using a date format of dd.mm.yyyy
*/
function displayDatePicker(dateFieldName, displayBelowThisObject, dtFormat, dtSep)
{
  var targetDateField = document.getElementsByName (dateFieldName).item(0);
 
  // if we weren't told what node to display the datepicker beneath, just display it
  // beneath the date field we're updating
  if (!displayBelowThisObject)
    displayBelowThisObject = targetDateField;
 
  // if a date separator character was given, update the dateSeparator variable
  if (dtSep)
    dateSeparator = dtSep;
  else
    dateSeparator = defaultDateSeparator;
 
  // if a date format was given, update the dateFormat variable
  if (dtFormat)
    dateFormat = dtFormat;
  else
    dateFormat = defaultDateFormat;
 
  var x = displayBelowThisObject.offsetLeft;
  var y = displayBelowThisObject.offsetTop + displayBelowThisObject.offsetHeight ;
 
  // deal with elements inside tables and such
  var parent = displayBelowThisObject;
  while (parent.offsetParent) {
    parent = parent.offsetParent;
    x += parent.offsetLeft;
    y += parent.offsetTop ;
  }
 
  drawDatePicker(targetDateField, x, y);
}


/**
Draw the datepicker object (which is just a table with calendar elements) at the
specified x and y coordinates, using the targetDateField object as the input tag
that will ultimately be populated with a date.

This function will normally be called by the displayDatePicker function.
*/
function drawDatePicker(targetDateField, x, y)
{
  var dt = getFieldDate(targetDateField.value );
 
  // the datepicker table will be drawn inside of a <div> with an ID defined by the
  // global datePickerDivID variable. If such a div doesn't yet exist on the HTML
  // document we're working with, add one.
  if (!document.getElementById(datePickerDivID)) {
    // don't use innerHTML to update the body, because it can cause global variables
    // that are currently pointing to objects on the page to have bad references
    //document.body.innerHTML += "<div id='" + datePickerDivID + "' class='dpDiv'></div>";
    var newNode = document.createElement("div");
    newNode.setAttribute("id", datePickerDivID);
    newNode.setAttribute("class", "dpDiv");
    newNode.setAttribute("style", "visibility: hidden;");
    document.body.appendChild(newNode);
  }
 
  // move the datepicker div to the proper x,y coordinate and toggle the visiblity
  var pickerDiv = document.getElementById(datePickerDivID);
  pickerDiv.style.position = "absolute";
  pickerDiv.style.left = x + "px";
  pickerDiv.style.top = y + "px";
  pickerDiv.style.visibility = (pickerDiv.style.visibility == "visible" ? "hidden" : "visible");
  pickerDiv.style.display = (pickerDiv.style.display == "block" ? "none" : "block");
  pickerDiv.style.zIndex = 10000;
 
  // draw the datepicker table
  refreshDatePicker(targetDateField.name, dt.getFullYear(), dt.getMonth(), dt.getDate());
}


/**
This is the function that actually draws the datepicker calendar.
*/
function refreshDatePicker(dateFieldName, year, month, day)
{
  // if no arguments are passed, use today's date; otherwise, month and year
  // are required (if a day is passed, it will be highlighted later)
  var thisDay = new Date();
 
  if ((month >= 0) && (year > 0)) {
    thisDay = new Date(year, month, 1);
  } else {
    day = thisDay.getDate();
    thisDay.setDate(1);
  }
 
  // the calendar will be drawn as a table
  // you can customize the table elements with a global CSS style sheet,
  // or by hardcoding style and formatting elements below
  var crlf = "\r\n";
  var TABLE = "<table cols=7 class='dpTable'>" + crlf;
  var xTABLE = "</table>" + crlf;
  var TR = "<tr class='dpTR'>";
  var TR_title = "<tr class='dpTitleTR'>";
  var TR_days = "<tr class='dpDayTR'>";
  var TR_todaybutton = "<tr class='dpTodayButtonTR'>";
  var xTR = "</tr>" + crlf;
  var TD = "<td class='dpTD' onMouseOut='this.className=\"dpTD\";' onMouseOver=' this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
  var TD_title = "<td colspan=5 class='dpTitleTD'>";
  var TD_buttons = "<td class='dpButtonTD'>";
  var TD_todaybutton = "<td colspan=7 class='dpTodayButtonTD'>";
  var TD_days = "<td class='dpDayTD'>";
  var TD_selected = "<td class='dpDayHighlightTD' onMouseOut='this.className=\"dpDayHighlightTD\";' onMouseOver='this.className=\"dpTDHover\";' ";    // leave this tag open, because we'll be adding an onClick event
  var xTD = "</td>" + crlf;
  var DIV_title = "<div class='dpTitleText'>";
  var DIV_selected = "<div class='dpDayHighlight'>";
  var xDIV = "</div>";
 
  // start generating the code for the calendar table
  var html = TABLE;
 
  // this is the title bar, which displays the month and the buttons to
  // go back to a previous month or forward to the next month
  html += TR_title;
  html += TD_buttons + getButtonCode(dateFieldName, thisDay, -1, "&lt;") + xTD;
  html += TD_title + DIV_title + monthArrayLong[ thisDay.getMonth()] + " " + thisDay.getFullYear() + xDIV + xTD;
  html += TD_buttons + getButtonCode(dateFieldName, thisDay, 1, "&gt;") + xTD;
  html += xTR;
 
  // this is the row that indicates which day of the week we're on
  html += TR_days;
  for(i = 0; i < dayArrayShort.length; i++)
    html += TD_days + dayArrayShort[i] + xTD;
  html += xTR;
 
  // now we'll start populating the table with days of the month
  html += TR;
 
  // first, the leading blanks
  for (i = 0; i < thisDay.getDay(); i++)
    html += TD + "&nbsp;" + xTD;
 
  // now, the days of the month
  do {
    dayNum = thisDay.getDate();
    TD_onclick = " onclick=\"updateDateField('" + dateFieldName + "', '" + getDateString(thisDay) + "');\">";
    
    if (dayNum == day)
      html += TD_selected + TD_onclick + DIV_selected + dayNum + xDIV + xTD;
    else
      html += TD + TD_onclick + dayNum + xTD;
    
    // if this is a Saturday, start a new row
    if (thisDay.getDay() == 6)
      html += xTR + TR;
    
    // increment the day
    thisDay.setDate(thisDay.getDate() + 1);
  } while (thisDay.getDate() > 1)
 
  // fill in any trailing blanks
  if (thisDay.getDay() > 0) {
    for (i = 6; i > thisDay.getDay(); i--)
      html += TD + "&nbsp;" + xTD;
  }
  html += xTR;
 
  // add a button to allow the user to easily return to today, or close the calendar
  var today = new Date();
  var todayString = "Today is " + dayArrayMed[today.getDay()] + ", " + monthArrayMed[ today.getMonth()] + " " + today.getDate();
  html += TR_todaybutton + TD_todaybutton;
  html += "<button class='dpTodayButton' onClick='refreshDatePicker(\"" + dateFieldName + "\");'>this month</button> ";
  html += "<button class='dpTodayButton' onClick='updateDateField(\"" + dateFieldName + "\");'>close</button>";
  html += xTD + xTR;
 
  // and finally, close the table
  html += xTABLE;
 
  document.getElementById(datePickerDivID).innerHTML = html;
  // add an "iFrame shim" to allow the datepicker to display above selection lists
  adjustiFrame();
}


/**
Convenience function for writing the code for the buttons that bring us back or forward
a month.
*/
function getButtonCode(dateFieldName, dateVal, adjust, label)
{
  var newMonth = (dateVal.getMonth () + adjust) % 12;
  var newYear = dateVal.getFullYear() + parseInt((dateVal.getMonth() + adjust) / 12);
  if (newMonth < 0) {
    newMonth += 12;
    newYear += -1;
  }
 
  return "<button class='dpButton' onClick='refreshDatePicker(\"" + dateFieldName + "\", " + newYear + ", " + newMonth + ");'>" + label + "</button>";
}


/**
Convert a JavaScript Date object to a string, based on the dateFormat and dateSeparator
variables at the beginning of this script library.
*/
function getDateString(dateVal)
{
  var dayString = "00" + dateVal.getDate();
  var monthString = "00" + (dateVal.getMonth()+1);
  dayString = dayString.substring(dayString.length - 2);
  monthString = monthString.substring(monthString.length - 2);
 
  switch (dateFormat) {
    case "dmy" :
      return dayString + dateSeparator + monthString + dateSeparator + dateVal.getFullYear();
    case "ymd" :
      return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString;
    case "ymd_235959" :	
      return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString + " 23:59:59";
    case "ymd_000000" :
      return dateVal.getFullYear() + dateSeparator + monthString + dateSeparator + dayString + " 00:00:00";
    case "mdy" :
    default :
      return monthString + dateSeparator + dayString + dateSeparator + dateVal.getFullYear();
  }
}


/**
Convert a string to a JavaScript Date object.
*/
function getFieldDate(dateString)
{
  var dateVal;
  var dArray;
  var d, m, y;
 
  try {
    dArray = splitDateString(dateString);
    if (dArray) {
      switch (dateFormat) {
        case "dmy" :
          d = parseInt(dArray[0], 10);
          m = parseInt(dArray[1], 10) - 1;
          y = parseInt(dArray[2], 10);
          break;
        case "ymd" :
		case "ymd_235959":
		case "ymd_000000":
          d = parseInt(dArray[2], 10);
          m = parseInt(dArray[1], 10) - 1;
          y = parseInt(dArray[0], 10);
          break;
        case "mdy" :
        default :
          d = parseInt(dArray[1], 10);
          m = parseInt(dArray[0], 10) - 1;
          y = parseInt(dArray[2], 10);
          break;
      }
      dateVal = new Date(y, m, d);
    } else if (dateString) {
      dateVal = new Date(dateString);
    } else {
      dateVal = new Date();
    }
  } catch(e) {
    dateVal = new Date();
  }
 
  return dateVal;
}


/**
Try to split a date string into an array of elements, using common date separators.
If the date is split, an array is returned; otherwise, we just return false.
*/
function splitDateString(dateString)
{
  var dArray;
  if (dateString.indexOf("/") >= 0)
    dArray = dateString.split("/");
  else if (dateString.indexOf(".") >= 0)
    dArray = dateString.split(".");
  else if (dateString.indexOf("-") >= 0)
    dArray = dateString.split("-");
  else if (dateString.indexOf("\\") >= 0)
    dArray = dateString.split("\\");
  else
    dArray = false;
 
  return dArray;
}

/**
Update the field with the given dateFieldName with the dateString that has been passed,
and hide the datepicker. If no dateString is passed, just close the datepicker without
changing the field value.

Also, if the page developer has defined a function called datePickerClosed anywhere on
the page or in an imported library, we will attempt to run that function with the updated
field as a parameter. This can be used for such things as date validation, setting default
values for related fields, etc. For example, you might have a function like this to validate
a start date field:

function datePickerClosed(dateField)
{
  var dateObj = getFieldDate(dateField.value);
  var today = new Date();
  today = new Date(today.getFullYear(), today.getMonth(), today.getDate());
 
  if (dateField.name == "StartDate") {
    if (dateObj < today) {
      // if the date is before today, alert the user and display the datepicker again
      alert("Please enter a date that is today or later");
      dateField.value = "";
      document.getElementById(datePickerDivID).style.visibility = "visible";
      adjustiFrame();
    } else {
      // if the date is okay, set the EndDate field to 7 days after the StartDate
      dateObj.setTime(dateObj.getTime() + (7 * 24 * 60 * 60 * 1000));
      var endDateField = document.getElementsByName ("EndDate").item(0);
      endDateField.value = getDateString(dateObj);
    }
  }
}

*/
function updateDateField(dateFieldName, dateString)
{
  var targetDateField = document.getElementsByName (dateFieldName).item(0);
  if (dateString)
    targetDateField.value = dateString;
 
  var pickerDiv = document.getElementById(datePickerDivID);
  pickerDiv.style.visibility = "hidden";
  pickerDiv.style.display = "none";
 
  adjustiFrame();
  targetDateField.focus();
 
  // after the datepicker has closed, optionally run a user-defined function called
  // datePickerClosed, passing the field that was just updated as a parameter
  // (note that this will only run if the user actually selected a date from the datepicker)
  if ((dateString) && (typeof(datePickerClosed) == "function"))
    datePickerClosed(targetDateField);
}


/**
Use an "iFrame shim" to deal with problems where the datepicker shows up behind
selection list elements, if they're below the datepicker. The problem and solution are
described at:

http://dotnetjunkies.com/WebLog/jking/archive/2003/07/21/488.aspx
http://dotnetjunkies.com/WebLog/jking/archive/2003/10/30/2975.aspx
*/
function adjustiFrame(pickerDiv, iFrameDiv)
{
  // we know that Opera doesn't like something about this, so if we
  // think we're using Opera, don't even try
  var is_opera = (navigator.userAgent.toLowerCase().indexOf("opera") != -1);
  if (is_opera)
    return;
  
  // put a try/catch block around the whole thing, just in case
  try {
    if (!document.getElementById(iFrameDivID)) {
      // don't use innerHTML to update the body, because it can cause global variables
      // that are currently pointing to objects on the page to have bad references
      //document.body.innerHTML += "<iframe id='" + iFrameDivID + "' src='javascript:false;' scrolling='no' frameborder='0'>";
      var newNode = document.createElement("iFrame");
      newNode.setAttribute("id", iFrameDivID);
      newNode.setAttribute("src", "javascript:false;");
      newNode.setAttribute("scrolling", "no");
      newNode.setAttribute ("frameborder", "0");
      document.body.appendChild(newNode);
    }
    
    if (!pickerDiv)
      pickerDiv = document.getElementById(datePickerDivID);
    if (!iFrameDiv)
      iFrameDiv = document.getElementById(iFrameDivID);
    
    try {
      iFrameDiv.style.position = "absolute";
      iFrameDiv.style.width = pickerDiv.offsetWidth;
      iFrameDiv.style.height = pickerDiv.offsetHeight ;
      iFrameDiv.style.top = pickerDiv.style.top;
      iFrameDiv.style.left = pickerDiv.style.left;
      iFrameDiv.style.zIndex = pickerDiv.style.zIndex - 1;
      iFrameDiv.style.visibility = pickerDiv.style.visibility ;
      iFrameDiv.style.display = pickerDiv.style.display;
    } catch(e) {
    }
 
  } catch (ee) {
  }
 
}


// **** Date Picker <<


//For Textbook Online Promo (Free e-assessment packages)
//Check that user has selected the number of paackages he/she is allocated.
function checkPkgSelected_TextbkOnlinePromo2008(numPkgAllocated)
{
	
	var i;
	var cnt = 0;
	for (i=0; i<document.getElementsByName('pkg[]').length; i++)
	{
		var elm = document.getElementsByName("pkg[]")[i];
		
		if (elm.checked)
		{
			++cnt;
		}
	}
	
	if (numPkgAllocated != cnt)
	{
		alert ("You are entitled to " + numPkgAllocated + " free combo packages but you selected " + cnt + ".\nPlease select " + numPkgAllocated + " combo packages from the list provided.");
		
		return false;
	}
	
	return true;	
}


//AJAX: Show create child form.
function displayCreateChild(bShow, sPath)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
		
	var url = sPath + "ajx/formcreatechild.php";
	url = url + "?sid=" + Math.random();	//Prevent server sending back cache data.
	
	if (bShow)
		url = url + "&action=shwfrm";	//Display the form.
		
	var elmFormCreateChild = document.getElementById('frmCreateChild');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			elmFormCreateChild.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Show additional create child form.
function listCreateChildFormMultiple(numAdditionalForm, sPath)
{
	if ( !isNumeric(numAdditionalForm) || 
		 numAdditionalForm < 1 ||
		 numAdditionalForm > 4 )
	{
		alert ("Please enter a number 1 to 4.");
		return false;
	}

	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}	
	
	var url = sPath + "ajx/formcreatechildmultiple.php";
	url = url + "?numform=" + numAdditionalForm;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.

	var elmFormCreateChild = document.getElementById('createChildForm');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;								
			elmFormCreateChild.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Show create child form.
//A customised version of displayCreateChild function.
//sCallingScript is the script where the Check ID button is called (eg "checkout_items" for script "checkout_items.php").
function displayCreateChildCustom(bShow, sPath, sCallingScript)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}	
	
	var url = sPath + "ajx/formcreatechildcustom.php";
	url = url + "?callingscript=" + sCallingScript;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	if (bShow)
		url = url + "&action=shwfrm";	//Display the form.
		
	var elmFormCreateChild = document.getElementById('frmCreateChild');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			elmFormCreateChild.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Register user ID with Science Score.
//Registered Login ID has the following convention: <parent ID>_<lvl>. eg. alice123_LG (where parent ID = alice123, lvl=LG)
function registerScienceScore(sLogid, sLvl)
{	
	if (sLogid == "" || sLvl == "")
		return;
		
	winRef = window.open("http://www.sciencescore.com/popular/poptest1.php?plogin=" + sLogid + "&lvl=" + sLvl + "&flg=r");	

	setTimeout("window.location.reload()", 4000); //Refresh the window after a while so that activated package will be reflected.
	
	return true;	//Always returns true no matter what.
}


//Register an account with eTutor.
function registerETutor(sLogid, sPkgCode, sDisplayName)
{	
	if (sLogid == "" || sPkgCode == "" || sDisplayName == "")
		return;
	
	//Register account.
	winRef = window.open("http://www.etutoronline.net/user_activated.asp?plogin=" + sLogid + "&pkg=" + sPkgCode + "&pname=" + sDisplayName);

	setTimeout("window.location.reload()", 4000); //Refresh the window after a while so that activated package will be reflected.

	return true;	//Always returns true no matter what.
	
}


//HeyMath's login process: Open new window to submit form.
function loginHeyMath(sNewWin, myForm)
{	
	window.open("", sNewWin, "");
	var a = window.setTimeout("document.heymathloginform.submit();", 500);
}

//Science Score login process: Open new window at a website.
function loginScienceScore(sLogid, sType)
{
	sAddr = "http://www.sciencescore.com/popular/poptest1.php?loginid=" + sLogid + "&flg=" + sType;
	window.open(sAddr);
}

//ETutor login process: Open new window at a website.
function loginETutor(sLogid)
{
	sAddr = "http://www.etutoronline.net/venderLogin.asp?userid=" + sLogid;
	window.open(sAddr);
}



function prePaymentCheck(numOfPkg)
{
	var i;
	var name;
	for (i=1; i<=numOfPkg; i++)
	{
		name = "pkg" + i;
		var elmSelect = document.getElementById(name);
		
		if (elmSelect.options[elmSelect.selectedIndex].value == "")
		{
			alert("Please assign all packages to your child account before proceeding.\nCreate new child account if you do not have any.");
			
			return false;
		}
	}
	
	return true;
}


//Set package's misc info (eg. event identity, remarks, etc.) entered in 1st package to all the rest of the packages.
function setMiscInfoToAllPkgs(miscInfoCount)
{
	//Get elements of 1st misc info.
	elmEventSel = document.getElementById("evtsel1");
	elmEventRmk = document.getElementById("evtrmk1");

	//Assign the misc to all packages.
	for (var i=2; i<=miscInfoCount; i++)
	{
		elmSel = document.getElementById("evtsel" + i);
		elmRmk = document.getElementById("evtrmk" + i);
		
		eval("elmSel.selectedIndex = elmEventSel.selectedIndex");
		eval("elmRmk.value = elmEventRmk.value");
	}
}



//AJAX: Set the misc info for all the packages.
function pkgSetMiscInfoForAll(miscInfoCount, sPath)
{			
	elmEventSel = document.getElementById("evtsel1");
	elmEventRmk = document.getElementById("evtrmk1");
	
	var remarks = elmEventRmk.value.trim();
	var eventIdty = elmEventSel.options[elmEventSel.selectedIndex].value;

	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			
			result = trimNewLine(result);
			
			if (result == 'set')
			{			
				alert ("Set.");
				setMiscInfoToAllPkgs(miscInfoCount);
				return true;
			}
			else
			{			
				alert ("Error setting. " + result);
				return false;
			}
		}
	}
			
	var url = sPath + "ajx/pkgsetmiscinfoforall.php";
	url = url + "?sid=" + Math.random();	//Prevent server sending back cache data.
		
	var params = "remarks=" + encodeURIComponent(remarks);
	params = params + "&eventidty=" + encodeURIComponent(eventIdty);

	xmlHttp.open("POST", url, true);

	//Send the proper header information along with the request
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", params.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	xmlHttp.send(params);	
}


//AJAX: Set the remarks for the package.
function pkgSetRemarks(eType, pkgId, sRemarks, sPath)
{			
	var remarks = sRemarks.trim();

	if (eType == "" || pkgId == "")
		return;

	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			
			result = trimNewLine(result);
			
			if (result == 'set')
				return true;
			else
				return false;
		}
	}
	
	var url = sPath + "ajx/pkgsetremarks.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	var params = "remarks=" + encodeURIComponent(remarks);
	
	xmlHttp.open("POST", url, true);

	//Send the proper header information along with the request
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", params.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	xmlHttp.send(params);		
}


//AJAX: Set event to package.
function pkgSetEvent(eType, pkgId, eventIdty, sPath)
{			
	if (eType == "" || pkgId == "")
		return;
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = sPath + "ajx/pkgsetevent.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&eventidty=" + eventIdty;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			
			result = trimNewLine(result);
			
			if (result == 'set')
				return true;
			else
				return false;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Assign package to student.
function pkgAssignStudent(eType, pkgId, studentId, sPath)
{			
	if (eType == "" || pkgId == "" || studentId == "")
		return;
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = sPath + "ajx/pkgassignstudent.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&acctid=" + studentId;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 
			
			var result = xmlHttp.responseText;
			
			result = trimNewLine(result);
			
			if (result == 'assigned')
				return true;
			else
				return false;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Assign package to student.
function pkgAssignStudent2(eType, pkgId, qtyCntr, studentId, sPath)
{					
	if (eType == "" || pkgId == "" || studentId == "")
		return;
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = sPath + "ajx/pkgassignstudent2.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&qtycntr=" + qtyCntr;
	url = url + "&acctid=" + studentId;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;			
			result = trimNewLine(result);
			
			if (result == 'assigned')
				return true;
			else
			{			
				alert ("Error assigning the student. " + result);
				return false;
			}
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Assign package to student. This version includes bundle type (cart type).
function pkgAssignStudent3(cartType, pkgId, eType, subPkgId, qtyCntr, studentId, sPath)
{					
	if (cartType == "" || pkgId == "" || studentId == "")
		return;
		
	if (eType == "")
		eType = cartType;
	if (subPkgId == "")
		subPkgId = 0;
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = sPath + "ajx/pkgassignstudent3.php";
	url = url + "?carttype=" + cartType;
	url = url + "&pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&subpkgid=" + subPkgId;
	url = url + "&qtycntr=" + qtyCntr;
	url = url + "&acctid=" + studentId;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;			
			result = trimNewLine(result);
			
			if (result == 'assigned')
				return true;
			else
			{			
				alert ("Error assigning the student. " + result);
				return false;
			}
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Remove the assigned student list. This is usually because the quantity of package/bundle is changed.
//This is to make sure the list is recreated.
function removeAssignedStudent(cartType, pkgId, sPath)
{					
	if (cartType == "" || pkgId == "")
		return;
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = sPath + "ajx/removeassignedstudent.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&carttype=" + cartType;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;			
			result = trimNewLine(result);
			
			if (result == 'done')
				return true;
			else
			{			
				alert ("Error removing the student list: " + result);
				return false;
			}
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}

//AJAX: Retrieve login details.
function retrieveLoginDetails(sEmail, sSecureAns)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 
			var result = xmlHttp.responseText;
			result = trimNewLine(result);
			
			if (result == 'detailssent')
			{			
				alert ("Your login details are sent to your email.");
				return true;
			}
			else if (result == 'wrongans')
			{			
				alert ("You security answer is not correct. Please enter again.");
				return false;
			}
			else if (result == 'notfound')
			{
				alert ("Data not found in database.");
				return false;
			}
			{			
				alert ("Error in retrieving details. Received: " + result);
				return false;
			}		
		}
	}	
	
	var email = sEmail.toLowerCase().trim();
	var secureans = sSecureAns.toLowerCase().trim();
	
	var url = "ajx/retrievelogin.php";	
	url = url + "?sid=" + Math.random();	//Prevent server sending back cache data.
	
	var params = "email=" + encodeURIComponent(email);
	params = params + "&secureans=" + encodeURIComponent(secureans);
	
	xmlHttp.open("POST", url, true);

	//Send the proper header information along with the request
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", params.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	xmlHttp.send(params);	
}


//Check that the details for retrieving login details are OK.
function checkRetrieveLoginDetailsInput(sEmail)
{
	var stremail = sEmail.trim();
	stremail = stremail.toLowerCase();
	
	if ( !checkEmail(stremail) )
	{
		alert("Invalid email.");
		return false;
	}
	
	return true;
}


//Confirm the assignment of the package to the parent.
function cfmAssignSelection(evtSel)
{
	for (var j=1; j<=evtSel; j++)
	{   
		elmEventSel = document.getElementById("evtsel" + j);
	
		if ( elmEventSel.options[elmEventSel.selectedIndex].value == "" )
      	{
      		alert("Please ensure event identities are set for all packages.");
			return false;
      	}
	}
	
	var selectValue = '';
	
	for (var i=0; i<document.assignfrm.assignpar.length; i++)
	{   
		if (document.assignfrm.assignpar[i].checked)
      	{
      		var selectValue = document.assignfrm.assignpar[i].value;
      	}
	}	
	
	if (selectValue == '')
	{
		alert("Please select a parent to assign to.\nCreate a parent account if none available.");
		return false;
	}
			
	return confirm("Confirm assign items to selected parent account?");
}


//Confirm the assignment of the package to the parent.
function cfmAssignSelection2()
{		
	var errMsg = "";	
	
	if (document.getElementById("rmk").value.length > 200) //Check remark length.
	{
		if (errMsg != "")
			errMsg += "\n";
				
		errMsg += "Please do not use more than 200 characters in remarks.";
	}
	
	//Check that all price paid values are numeric.
	var elmPricePaid = k_getElementsByClassName(document.assignfrm, 'input', 'pricePaid');
	
	for (var i=0; i<elmPricePaid.length; i++)
	{		
		if ( !isNumeric(elmPricePaid[i].value) )
		{
			if (errMsg != "")
				errMsg += "\n";
				
			errMsg += "Please enter only numeric in all Price Paid fields."
			break;
		}
	}
	
	//Check event selected.
	elmEventSel = document.assignfrm.evt;	
	if ( elmEventSel.options[elmEventSel.selectedIndex].value == "" )
    {
		if (errMsg != "")
			errMsg += "\n";
				
      	errMsg += "Please select an event.";
    }
	
	//Check purchase date entered.
	if ( document.assignfrm.purchasedate.value == "" )
    {
		if (errMsg != "")
			errMsg += "\n";
				
      	errMsg += "Please enter purchase date.";
    }
	
	//Check assigned a parent account.
	var selectValue = '';	

	for (var i=0; i<document.assignfrm.selpar.length; i++)
	{   
		if (document.assignfrm.selpar[i].checked)
      	{
      		var selectValue = document.assignfrm.selpar[i].value;
			break;
      	}
	}	
	if (selectValue == "")
	{
		if (errMsg != "")
			errMsg += "\n";
				
		errMsg += "Please select a parent to assign.";
	}
		
	//Any error message, fault out.
	if (errMsg != "")
	{
		alert (errMsg);
		return false;
	}
	
	//No error, prompt for assign confirmation.
	return confirm("Confirm assign items to selected parent account?");
}


//Prompt to confirm if to delete account. If so, redirect it to specified address.
function cfmDeleteAcct(sAddr)
{
	if ( !confirm("All results linked to the child account will be deleted.\nConfirm delete account?") )
		return false;
	
	redirect(sAddr);
}


//Administrative: Check data for loading worksheet data into package. 
//No promoting of worksheet record removal.
function checkLoadPkgWksht2(sFilePath)
{
	if (sFilePath.trim() == '')
	{
		alert("Please locate an XML file to use for worksheet loading.");
		return false;
	}
	
	var fileExt = sFilePath.substr(sFilePath.length - 3);
		
	if ( fileExt.toLowerCase() != "xml" )
	{
		alert("Please use only XML file for loading.");
		return false;
	}
		
	return true;
}


//Administrative: Check data for loading worksheet data into package.
function checkLoadPkgWksht(sFilePath)
{
	if (sFilePath.trim() == '')
	{
		alert("Please locate an XML file to use for worksheet loading.");
		return false;
	}
	
	var fileExt = sFilePath.substr(sFilePath.length - 3);
		
	if ( fileExt.toLowerCase() != "xml" )
	{
		alert("Please use only XML file for loading.");
		return false;
	}
	
	if ( !confirm("All existing worksheets will be removed. Continue?") )
		return false;
		
	return true;
}


//Administrative: Check image extension type to be loaded for package.
function checkLoadImgExt(sFilePath)
{
	var extArray = new Array('.jpg', 'jpeg', '.gif', '.png');	//All must lowercase.
	var i;
	
	var filepathlower = sFilePath.toLowerCase();
		
	if (filepathlower == '')
	{
		alert("Please locate an image file.");
		return false;
	}
	
	for (i in extArray)
	{
		if (filepathlower.lastIndexOf(extArray[i]) != -1)
		{
			//alert("Found!");
			return true;
		}			
	}
	
	alert("Only use only JPG, JPEG, GIF or PNG image file.");
	return false;
	
}


//AJAX: Set navigational redirectional data
//sAddrBefore is the web address to redirect immediately after setting the SESSION redirecting web addr (sAddrAfter).
function setNavAndRedirect(sAddrBefore, sAddrAfter)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	//xmlHttp.onreadystatechange = getIdAvailibility;
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
			redirect(sAddrBefore);
	}	
	
	var url = "ajx/navset.php";	
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	var params = "webaddr=" + encodeURIComponent(sAddrAfter);
	xmlHttp.open("POST", url, true);

	//Send the proper header information along with the request
	xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlHttp.setRequestHeader("Content-length", params.length);
	xmlHttp.setRequestHeader("Connection", "close");
	
	xmlHttp.send(params);
}


//AJAX: Remove item from cart.
function removeItemFromCart(pkgId, eType)
{			
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
	
	var url = "ajx/removefromcart.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	var elmCartItem = document.getElementById('cartItems');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;					
			elmCartItem.innerHTML = result;
						
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Add item to cart.
function addItemToCart(pkgId, eType)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
		
	var url = "ajx/addtocart.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	var elmCartItem = document.getElementById('cartItems');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			elmCartItem.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);		
}


//AJAX: Add item to cart from the product detail page.
function addItemToCartFromPdtDetails(pkgId, eType)
{		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}	
	
	var url = "ajx/addtocart.php";
	url = url + "?pkgid=" + pkgId;
	url = url + "&etype=" + eType;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	var elmCartItem = window.opener.document.getElementById('cartItems');
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;
			
			//If parent window is not display shopping cart, display it.
			//var parentUrl = window.opener.location.href;
			var parentUrl = window.location.href;
			if ( parentUrl.indexOf("shop.php") == -1 )
				window.opener.location.href = "http://www.edupop.com.sg/shop.php";

			elmCartItem.innerHTML = result;
			window.close();	//Close product details window after adding to cart.
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);
}


//Function to swap image.
function imgSwap(sElmName, sImgName)
{
	document[sElmName].src = sImgName;
}


//List the levels selected base on the level type selected.
function listLevels(sLevelType, sLevelList)
{
	var tmp = "<p>Level: <select name='level' id='level' style='width:150px;'>";
	
	tmp += "<option value=''>Select level</option>";
	
	if (sLevelType == "pri") //Pri 1 to 6.
	{
		tmp += "<option value='p1'>Primary 1</option><option value='p2'>Primary 2</option><option value='p3'>Primary 3</option><option value='p4'>Primary 4</option><option value='p5'>Primary 5</option><option value='p6'>Primary 6</option>";
	}	
	else if (sLevelType == "sec") //Pri 1 to 6.
	{
		tmp += "<option value='s1'>Secondary 1</option><option value='s2'>Secondary 2</option><option value='s3'>Secondary 3</option><option value='s4'>Secondary 4</option>";
	}
	
	tmp += "</select></p>";
	
	var elmLevel = document.getElementById(sLevelList);	
	elmLevel.innerHTML = tmp;
}


//AJAX: List the products for user to purchase.
function listProducts(sElmPdt, sEType, sLevel)
{	
	var levelTag = document.getElementById(sLevel).value;
	
	if (levelTag == "")
	{
		return false;
	}
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
			
	var url = "ajx/listproducts.php";
	url = url + "?etype=" + sEType;
	url = url + "&leveltag=" + levelTag;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
		
	var elmPdt = document.getElementById(sElmPdt);
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;					
			elmPdt.innerHTML = result;
						
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//List the subject base on level selected.
function listSubject(levelId, sSbj)
{
	var tmp = "<p>Subject: <select name='sbjid' id='sbjid' style='width:150px;'>";	
	tmp += "<option value=''></option>";
	
	if (levelId > 3 && levelId < 10) //Pri 1 to 6.
	{
		tmp += "<option value='1'>Math</option><option value='2'>English</option><option value='3'>Chinese</option>";
	}
	
	if (levelId > 5 && levelId < 10) //Pri 3 to 6.
	{
		tmp += "<option value='4'>Science</option>";
	}
	
	tmp += "</select></p>";
	
	var elmSbj = document.getElementById(sSbj);	
	elmSbj.innerHTML = tmp;
}


//Not used.
function displayProducts(sElm, sEType, sLevel, sSbj)
{
	var elmPdt = document.getElementById(sElm);
	
	var str = "";
	
	if (sEType == "eassess")
	{
		str = "E-Assessment";
	}
	else if (sEType == "elearn")
	{
		str = "E-Learning";
	}
		
	
	var levelId = document.getElementById(sLevel).value;
	var sbjId = document.getElementById(sSbj).value;
	
	if (levelId == "" || sbjId == "")
	{
		alert("Please select both level and subject.");
		return false;
	}
	
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
		
	var url = "ajx/listproducts.php";
	url = url + "?etype=" + sEType;
	url = url + "&levelid=" + levelId;
	url = url + "&sbjid=" + sbjId;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;					
			elmPdt.innerHTML = result;
						
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//AJAX: Get and rewrite the worksheet attempted range base on the numbered link that is clicked.
function getWorksheetAttemptRange(sElm, latestAttempt, highAttempt, lowAttempt, wkshtId, wkshtType, acctId)
{
	var elm = document.getElementById(sElm);
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		alert ("\nSorry. Your browser does not support AJAX.");
		return false;		//Return false if there's error..
  	}
			
	var url = "ajx/wkshtattempt.php";
	url = url + "?wkshtid=" + wkshtId;
	url = url + "&type=" + wkshtType;
	url = url + "&acctid=" + acctId;
	url = url + "&latestattempt=" + latestAttempt;
	url = url + "&highrange=" + highAttempt;
	url = url + "&lowrange=" + lowAttempt;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		if (xmlHttp.readyState == 4)
		{ 			
			var result = xmlHttp.responseText;					
			elm.innerHTML = result;
			
			return true;
		}
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//Check whether package assignment is OK.
function chkAssignPkgToStudent(sIdToAssign, sOrgAssign)
{
	if (sIdToAssign == '')
	{
		alert ("Please select a child before assigning.\nCreate one if you have not yet done so.");
		return false;
	}
	else if (sIdToAssign == sOrgAssign)
	{
		alert ("Child already assigned to package.");
		return false;
	}
	else
		return confirm("Confirm assign package to the child?");
}


function unchkId(elmCkId)
{
	if (elmCkId)
		elmCkId.checked = false;
}


//Returns true if ID available for use.
function getIdAvailibility(elmCkId) 
{ 	
	if (xmlHttp.readyState == 4)
	{ 
		var result = xmlHttp.responseText;
		var msg = '';
		
		result = trimNewLine(result);
		
		if (result == 'notexist')
		{
			if (elmCkId)
				elmCkId.checked = true;
					
			return true;
		}
		else
		{		
			if (elmCkId)
				elmCkId.checked = false;
				
			alert ("ID not available for use.");				
			return false;
		}			
	}
}


//AJAX
//Check database if ID (eg. package ID) is available for creation.
//sPath is dependent on where the function calling file is located. sPath must end with "/".
//Returns '' if User ID can be used. Else it will return the error message.
function checkId(sId, lenMinId, sDbTbl, sDbField, sPath, elmCkId)
{			
	var msg = '';
	
	if (sId.length < lenMinId)
  	{ 		
		msg = msg + "\ID must be at least " + lenMinId + " characters long."			
  	}
	
	if ( sId.indexOf(" ") != -1 )
  	{ 
		msg = msg + "\ID must not contain space."
  	}
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX."
  	}		
	
	if (msg != '')
	{
		if (elmCkId)
			elmCkId.checked = false;
		
		alert(msg);
			
		return false;		//Return false if there's error..
	}		
	
	var url = sPath + "ajx/existindb.php";
	url = url + "?chkfor=" + sId.toLowerCase();
	url = url + "&chktbl=" + sDbTbl;
	url = url + "&chkfield=" + sDbField;
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		return getIdAvailibility(elmCkId);
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//AJAX
//Check database if user ID is available for creation.
//Difference between this function and checkId is that it calls different ajax file. The difference in the ajax file is that this function's ajax hardcode the database tables to look up.
//sPath is dependent on where the function calling file is located. sPath must end with "/".
//Returns '' if User ID can be used. Else it will return the error message.
function checkUserId(sId, lenMinId, sPath, elmCkId)
{			
	var msg = '';
	
	if (sId.length < lenMinId)
  	{ 		
		msg = msg + "\ID must be at least " + lenMinId + " characters long."			
  	}
	
	if ( sId.indexOf(" ") != -1 )
  	{ 
		msg = msg + "\ID must not contain space."
  	}
	
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX."
  	}
		
	if (msg != '')
	{
		if (elmCkId)
			elmCkId.checked = false;
		
		alert(msg);
			
		return false;		//Return false if there's error..
	}	
	
	var url = sPath + "ajx/useridexistindb.php";
	url = url + "?chkfor=" + sId.toLowerCase();	//All logins in lowercase.
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		return getIdAvailibility(elmCkId);
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//Returns true if unique data available for use.
function getUniqueDataAvailibility(elmCkId) 
{ 	
	if (xmlHttp.readyState == 4)
	{ 
		var result = xmlHttp.responseText;
		var msg = '';
		
		result = trimNewLine(result);
		
		if (result == 'notexist')
		{
			if (elmCkId)
				elmCkId.checked = true;
			
			alert ("Check successful. User ID and email can be used.");				
			return true;
		}
		else
		{		
			if (elmCkId)
				elmCkId.checked = false;
			
			if (result == 'useridexist')
				msg = 'User ID not available for use.\n';				
			else if (result == 'emailexist')
				msg = 'Email not available for use.\n';
			else if (result == 'userid_email_exist')
				msg = 'User ID and email not available for use.\n';
				
			alert (msg);
			
			return false;
		}			
	}
}


//AJAX
//Check database if new account data are available for creation.
//Returns true if new acount unique data can be used. Else it will return false.
//Note: Enter "" for sEmail2 if only verifies 1 email.
function checkNewAcctDataUnique(sId, lenMinId, sEmail1, sEmail2, sPath, elmCkId)
{			
	var msg = '';
	var strsid = sId.trim();
	var stremail1 = sEmail1.trim();
	var stremail2 = sEmail2.trim();	
	
	strsid = strsid.toLowerCase();
	stremail1 = stremail1.toLowerCase();
	stremail2 = stremail2.toLowerCase();
		
	if (strsid.length < lenMinId)
  	{ 		
		msg = msg + "\nID must be at least " + lenMinId + " characters long.";		
  	}	

	var myRegxp = /^([a-zA-Z0-9_-]+)$/; //Only allow alphanumeric, "_" and "-" for user ID.
	if ( myRegxp.test(strsid) == false )
	{
		msg = msg + "\nID can only contain letters, numbers, underscore \"_\" or dash \"-\" characters."		
	}
	
	//Check that email is valid.
	if (stremail1 != stremail2)
	{
		msg += "\nEmails do not match.";
	}
	else if ( !checkEmail(stremail1) )
	{
		msg += "\nInvalid email.";
	}
		
	xmlHttp=GetXmlHttpObject();	//For AJAX.
	if (xmlHttp == null)	//Exit if Ajax not supported.
  	{
		msg = msg + "\nSorry. Your browser does not support AJAX.";
  	}
			
	if (msg != '')
	{
		if (elmCkId)
			elmCkId.checked = false;
		
		alert(msg);
			
		return false;		//Return false if there's error..
	}
		
	var url = sPath + "ajx/chk_new_acct_data_unique.php";
	url = url + "?userid=" + strsid;	//All logins in lowercase.
	url = url + "&email=" + stremail1;	//All logins in lowercase.
	url = url + "&sid=" + Math.random();	//Prevent server sending back cache data.
	
	xmlHttp.onreadystatechange = function()
	{
		return getUniqueDataAvailibility(elmCkId);
	}
	
	xmlHttp.open("GET", url, true);
	xmlHttp.send(null);	
}


//Verifies entries.
function checkEditVendor(sName)
{
	var result = true;
	var errmsg = '';
	
	var name = sName.trim();
			
	//Compulsory fields.
	if ( name == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkCreateVendor(sVendorID, sName, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var vendorid = sVendorID.trim();
	var name = sName.trim();
			
	if (!bChkId)
	{
		errmsg += "\nID not yet checked.";
		result = false;
	}
		
	//Compulsory fields.
	if ( vendorid == "" ||
		 name == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkCreatePkgElearn(sId, sVendor, lenMinId, sName, lenMaxName, Price, DiscountPrice, sDescription, lenMaxDesc, sSubjects, sLevels, sModRewrite, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var pkgid = sId.trim();
	var vendorid = sVendor.trim();
	var name = sName.trim();
	var price = Price.trim();
	var discountprice = DiscountPrice.trim();
	var description = sDescription.trim();
	
	var subjects = sSubjects.trim();
	var levels = sLevels.trim();
		
	var modrewrite = sModRewrite.trim();
		
	if (!bChkId)
	{
		errmsg += "\nPlease check whether package ID is available for use.";
		result = false;
	}
		
	//Compulsory fields.
	if ( pkgid == "" ||
		 vendorid == "" ||
		 name == "" ||
		 price == "" ||
		 description == "" ||
		 subjects == "" ||
		 levels == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}	
	
	if ( modrewrite != '' && modrewrite.indexOf(" ") != -1 ) //Error if contains space.
	{
		errmsg += "\nSpace not allowed in mod rewrite.";
		result = false;
	}
	
	if ( price != '' && !isNumeric(price) )
	{
		errmsg += "\nPrice should contain only decimal numbers. (no -ve)";
		result = false;
	}
		
	if ( discountprice != '' && !isNumeric(discountprice) )
	{
		errmsg += "\nDiscounted price should contain only decimal numbers. (no -ve)";
		result = false;
	}
	else if ( discountprice != '' && parseFloat(discountprice) >= parseFloat(price) )
	{
		errmsg += "\nDiscounted price should be lower than original price.";
		result = false;		
	}
	
	if (sName.length > lenMaxName)
	{
		errmsg += "\nYour package name is " + sName.length + " characters long, which should not be more than " + lenMaxName + " characters.";
		result = false;	
	}
	
	if (description.length > lenMaxDesc)
	{
		errmsg += "\nYour description is " + description.length + " characters long, which should not be more than " + lenMaxDesc + " characters.";
		result = false;	
	}
	
	var tmp = '';
	sjbArray = subjects.split(",");	//Split by comma, sLevels	
	for (var i=0; i<sjbArray.length; i++)
	{
		tmp = sjbArray[i].trim();		
		
		if ( indexInArray(subjectListArray, tmp) == -1 )	//subjectArray is global.
		{			
			errmsg += "\nPlease key in your subjects properly. Note to separate multiple subjects by comma \",\".";
			result = false;	
			break;	//Break out of the stupid loop. No need to check further since already has subject error.
		}
	}
	
	lvlArray = levels.split(",");	//Split by comma, sLevels	
	for (var i=0; i<lvlArray.length; i++)
	{
		tmp = lvlArray[i].trim();
		
		//Check that length of each level should be only 2 char long, 1st char is valid (eg. n, p or s, etc.), and subsequent char is numeric.
		if ( tmp.length != 2 || indexInArray( levelListArray, tmp.charAt(0) ) == -1 || !isNumeric(tmp.substr(1)) )	//levelListArray is global.
		{			
			errmsg += "\nPlease key in your levels properly. Note to separate multiple levels by comma \",\".";
			result = false;	
			
			break;	//Break out of the bloody loop. No need to check further since already has level error.
		}
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkEditPkgElearn(sName, lenMaxName, Price, DiscountPrice, sDescription, lenMaxDesc, sSubjects, sLevels, sModRewrite)
{
	var result = true;
	var errmsg = '';
	
	var name = sName.trim();
	var price = Price.trim();
	var discountprice = DiscountPrice.trim();
	var description = sDescription.trim();
	
	var subjects = sSubjects.trim();
	var levels = sLevels.trim();
	
	var modrewrite = sModRewrite.trim();
			
	//Compulsory fields.
	if ( name == "" ||
		 price == "" ||
		 description == "" ||
		 subjects == "" ||
		 levels == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}	
	
	if ( modrewrite != '' && modrewrite.indexOf(" ") != -1 ) //Error if contains space.
	{
		errmsg += "\nSpace not allowed in mod rewrite.";
		result = false;
	}
	
	if ( price != '' && !isNumeric(price) )
	{
		errmsg += "\nPrice should contain only decimal numbers. (no -ve)";
		result = false;
	}
	
	if ( discountprice != '' && !isNumeric(discountprice) )
	{
		errmsg += "\nDiscounted price should contain only decimal numbers. (no -ve)";
		result = false;
	}
	else if ( discountprice != '' && parseFloat(discountprice) >= parseFloat(price) )
	{
		errmsg += "\nDiscounted price should be lower than original price.";
		result = false;		
	}
	
	if (sName.length > lenMaxName)
	{
		errmsg += "\nYour package name is " + sName.length + " characters long, which should not be more than " + lenMaxName + " characters.";
		result = false;	
	}
		
	if (description.length > lenMaxDesc)
	{
		errmsg += "\nYour description is " + description.length + " characters long, which should not be more than " + lenMaxDesc + " characters.";
		result = false;	
	}
	
	var tmp = '';
	sjbArray = subjects.split(",");	//Split by comma, sLevels	
	for (var i=0; i<sjbArray.length; i++)
	{
		tmp = sjbArray[i].trim();
		
		if ( indexInArray(subjectListArray, tmp) == -1 )	//subjectArray is global.
		{			
			errmsg += "\nPlease key in your subjects properly. Note to separate multiple subjects by comma \",\".";
			result = false;	
			break;	//Break out of the stupid loop. No need to check further since already has subject error.
		}
	}
	
	lvlArray = levels.split(",");	//Split by comma, sLevels	
	for (var i=0; i<lvlArray.length; i++)
	{
		tmp = lvlArray[i].trim();
		
		//Check that length of each level should be only 2 char long, 1st char is valid (eg. n, p or s, etc.), and subsequent char is numeric.
		if ( tmp.length != 2 || indexInArray( levelListArray, tmp.charAt(0) ) == -1 || !isNumeric(tmp.substr(1)) )	//levelListArray is global.
		{			
			errmsg += "\nPlease key in your levels properly. Note to separate multiple levels by comma \",\".";
			result = false;	
			
			break;	//Break out of the bloody loop. No need to check further since already has level error.
		}
	}	
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkCreatePkg(sId, sVendor, lenMinId, sName, lenMaxName, Price, DiscountPrice, sDescription, lenMaxDesc, sSubjects, sLevels, sModRewrite, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var pkgid = sId.trim();
	var vendorid = sVendor.trim();
	var name = sName.trim();
	var price = Price.trim();
	var discountprice = DiscountPrice.trim();
	var description = sDescription.trim();
	
	var subjects = sSubjects.trim();
	var levels = sLevels.trim();
		
	var modrewrite = sModRewrite.trim();
		
	if (!bChkId)
	{
		errmsg += "\nPlease check whether package ID is available for use.";
		result = false;
	}
		
	//Compulsory fields.
	if ( pkgid == "" ||
		 vendorid == "" ||
		 name == "" ||
		 price == "" ||
		 description == "" ||
		 subjects == "" ||
		 levels == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	if ( modrewrite != '' && modrewrite.indexOf(" ") != -1 ) //Error if contains space.
	{
		errmsg += "\nSpace not allowed in mod rewrite.";
		result = false;
	}
	
	if ( price != '' && !isNumeric(price) )
	{
		errmsg += "\nPrice should contain only decimal numbers. (no -ve)";
		result = false;
	}
		
	if ( discountprice != '' && !isNumeric(discountprice) )
	{
		errmsg += "\nDiscounted price should contain only decimal numbers. (no -ve)";
		result = false;
	}
	else if ( discountprice != '' && parseFloat(discountprice) >= parseFloat(price) )
	{
		errmsg += "\nDiscounted price should be lower than original price.";
		result = false;		
	}
	
	if (sName.length > lenMaxName)
	{
		errmsg += "\nYour package name is " + sName.length + " characters long, which should not be more than " + lenMaxName + " characters.";
		result = false;	
	}
	
	if (description.length > lenMaxDesc)
	{
		errmsg += "\nYour description is " + description.length + " characters long, which should not be more than " + lenMaxDesc + " characters.";
		result = false;	
	}
		
	var tmp = '';
	sjbArray = subjects.split(",");	//Split by comma, sLevels	
	for (var i=0; i<sjbArray.length; i++)
	{
		tmp = sjbArray[i].trim();
		
		if ( indexInArray(subjectListArray, tmp) == -1 )	//subjectArray is global.
		{			
			errmsg += "\nPlease key in your subjects properly. Note to separate multiple subjects by comma \",\".";
			result = false;	
			break;	//Break out of the stupid loop. No need to check further since already has subject error.
		}
	}
	
	lvlArray = levels.split(",");	//Split by comma, sLevels	
	for (var i=0; i<lvlArray.length; i++)
	{
		tmp = lvlArray[i].trim();
		
		//Check that length of each level should be only 2 char long, 1st char is valid (eg. n, p or s, etc.), and subsequent char is numeric.
		if ( tmp.length != 2 || indexInArray( levelListArray, tmp.charAt(0) ) == -1 || !isNumeric(tmp.substr(1)) )	//levelListArray is global.
		{			
			errmsg += "\nPlease key in your levels properly. Note to separate multiple levels by comma \",\".";
			result = false;	
			
			break;	//Break out of the bloody loop. No need to check further since already has level error.
		}
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkEditPkg(sName, lenMaxName, Price, DiscountPrice, sDescription, lenMaxDesc, sSubjects, sLevels, sModRewrite)
{	
	var result = true;
	var errmsg = '';
	
	var name = sName.trim();
	var price = Price.trim();
	var discountprice = DiscountPrice.trim();
	var description = sDescription.trim();
	
	var subjects = sSubjects.trim();
	var levels = sLevels.trim();
	
	var modrewrite = sModRewrite.trim();
			
	//Compulsory fields.
	if ( name == "" ||
		 price == "" ||
		 description == "" ||
		 subjects == "" ||
		 levels == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	if ( modrewrite != '' && modrewrite.indexOf(" ") != -1 ) //Error if contains space.
	{
		errmsg += "\nSpace not allowed in mod rewrite.";
		result = false;
	}
	
	if ( price != '' && !isNumeric(price) )
	{
		errmsg += "\nPrice should contain only decimal numbers. (no -ve)";
		result = false;
	}
	
	if ( discountprice != '' && !isNumeric(discountprice) )
	{
		errmsg += "\nDiscounted price should contain only decimal numbers. (no -ve)";
		result = false;
	}
	else if ( discountprice != '' && parseFloat(discountprice) >= parseFloat(price) )
	{
		errmsg += "\nDiscounted price should be lower than original price.";
		result = false;		
	}
	
	if (sName.length > lenMaxName)
	{
		errmsg += "\nYour package name is " + sName.length + " characters long, which should not be more than " + lenMaxName + " characters.";
		result = false;	
	}
		
	if (description.length > lenMaxDesc)
	{
		errmsg += "\nYour description is " + description.length + " characters long, which should not be more than " + lenMaxDesc + " characters.";
		result = false;	
	}
	
	var tmp = '';
	sjbArray = subjects.split(",");	//Split by comma, sLevels	
	for (var i=0; i<sjbArray.length; i++)
	{
		tmp = sjbArray[i].trim();
		
		if ( indexInArray(subjectListArray, tmp) == -1 )	//subjectArray is global.
		{			
			errmsg += "\nPlease key in your subjects properly. Note to separate multiple subjects by comma \",\".";
			result = false;	
			break;	//Break out of the stupid loop. No need to check further since already has subject error.
		}
	}
	
	lvlArray = levels.split(",");	//Split by comma, sLevels	
	for (var i=0; i<lvlArray.length; i++)
	{
		tmp = lvlArray[i].trim();
		
		//Check that length of each level should be only 2 char long, 1st char is valid (eg. n, p or s, etc.), and subsequent char is numeric.
		if ( tmp.length != 2 || indexInArray( levelListArray, tmp.charAt(0) ) == -1 || !isNumeric(tmp.substr(1)) )	//levelListArray is global.
		{
			errmsg += "\nPlease key in your levels properly. Note to separate multiple levels by comma \",\".";
			result = false;	
			
			break;	//Break out of the bloody loop. No need to check further since already has level error.
		}
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
	
}


//Verifies entries.
function checkAcctCreateStudent(sUserID, lenMinUser, sFName, sLName, sPwd1, sPwd2, lenMinPwd, sSchool, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var userid = sUserID.trim();
	var fname = sFName.trim();
	var lname = sLName.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	var school = sSchool.trim();
			
	if (!bChkId)
	{
		errmsg += "\nPlease check whether user ID is available for use.";
		result = false;
	}
		
	//Compulsory fields.
	if ( userid == "" ||
		 fname == "" ||
		 lname == "" ||
		 pwd1 == "" ||
		 pwd2 == "" ||
		 school == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	//Check passwords.
	if ( pwd1 != pwd2 )
	{
		errmsg += "\nPasswords do not match.";
		result = false;
	}
	else if (pwd1.length < lenMinPwd)
	{
		errmsg = errmsg + "\nPassword must be minimum " + lenMinPwd + " characters.";
		result = false;
	}
		
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
	
}


//Verifies entries.
function checkAcctEditStudent(sFName, sLName, sPwd1, sPwd2, lenMinPwd, sSchool)
{
	var result = true;
	var errmsg = '';
	
	var fname = sFName.trim();
	var lname = sLName.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	var school = sSchool.trim();
			
	//Compulsory fields.
	if (fname == "" || 
		lname == "" || 
		school == "")
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	//Check passwords.	
	if (pwd1 != "" || pwd2 != "")
	{
		if (pwd1 != pwd2)
		{
			errmsg += "\nPasswords do not match.";
			result = false;
		}
		else if (pwd1.length < lenMinPwd)
		{
			errmsg += "\nPasswords must be minimum " + lenMinPwd + " characters.";
			result = false;
		}
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verifies entries.
function checkAcctCreateParentStudentMulti(lenMinUser, lenMinPwd)
{	
	var result = true;
	var errmsg = '';
	
	var userIdArray = new Array();	//Store all entered user IDs to check if there's duplicate.
	
	//Parent details.
	var paruserid = document.getElementById('paruser').value.trim();	
	userIdArray.push(paruserid);
	
	var parfname = document.getElementById('parfname').value.trim();	
	var parlname = document.getElementById('parlname').value.trim();
	var paremail = document.getElementById('paremail').value.trim();
	var parpwd = document.getElementById('parpwd').value.trim();
	var parcontactno = document.getElementById('parcontactno').value.trim();
	var paraddress = document.getElementById('paraddress').value.trim();
	var parpostcode = document.getElementById('parpostcode').value.trim();
			
	//Error if parent's User ID not yet checked.
	if (!document.getElementById('parckid').checked)
	{
		errmsg += "\nPARENT: Check if user ID and email are available for use.";
		result = false;
	}
		
	//Check user id.
	if (paruserid.length < lenMinUser)
	{
		errmsg = errmsg + "\nPARENT: User ID must be minimum " + lenMinUser + " characters.";
		result = false;
	}
	
	//Check that email is valid.
	if ( !checkEmail(paremail) )
	{
		errmsg += "\nPARENT: Invalid email.";
		result = false;
	}
		
	//Check passwords.
	if (parpwd.length < lenMinPwd)
	{
		errmsg = errmsg + "\nPARENT: Password must be minimum " + lenMinPwd + " characters.";
		result = false;
	}
	
	//Compulsory fields.
	if ( paruserid == "" ||
		 parfname == "" ||
		 parlname == "" ||
		 paremail == "" ||
		 parpwd == "" ||
		 parcontactno == "" ||
		 //parstate == "" ||
		 paraddress == "" ||
		 parpostcode == "" )
	{
		errmsg += "\nPARENT: Not all required fields(*) are entered.";
		result = false;
	}
	
	//Child's details.
	//At least Student Account 1 form must be used.
	if ( document.getElementById('stuuser1').value.trim() == "" &&
		 document.getElementById('stupwd1').value.trim() == "" )
	{
		errmsg += "\n\nSTUDENT 1: Form must be used to a create child account.";
		result = false;
	}
	
	//Get number of child creation forms.
	var numOfChild = document.getElementById('createNumChild').value.trim();
	
	var stuuser;	
	var stufname;	
	var stulname;
	var stupwd;
	var stuschool;
		
	for (var i=1; i<=numOfChild; i++)
	{
		var linebreak = false;
		
		stuuser = document.getElementById('stuuser' + i).value.trim();
		stupwd = document.getElementById('stupwd' + i).value.trim();
		
		//Don't check if user ID and password are empty because we assume user is not using the form.		
		if (stuuser == "" && stupwd == "")	
			continue;

		userIdArray.push(stuuser);

		stufname = document.getElementById('stufname' + i).value.trim();	
		stulname = document.getElementById('stulname' + i).value.trim();	
		
		//Error if child's User ID not yet checked.
		if (!document.getElementById('stuckid' + i).checked)
		{
			if (!linebreak)
			{
				errmsg += "\n";
				linebreak = true;
			}				
			errmsg += "\nSTUDENT " + i + ": Check if user ID is available for use.";
			result = false;
		}	
		
		//Check user id.
		if (stuuser.length < lenMinUser)
		{
			if (!linebreak)
			{
				errmsg += "\n";
				linebreak = true;
			}			
			errmsg = errmsg + "\nSTUDENT " + i + ": User ID must be minimum " + lenMinUser + " characters.";
			result = false;
		}	
		
		//Check passwords.
		if (stupwd.length < lenMinPwd)
		{
			if (!linebreak)
			{
				errmsg += "\n";
				linebreak = true;
			}
			errmsg = errmsg + "\nSTUDENT " + i + ": Password must be minimum " + lenMinPwd + " characters.";
			result = false;
		}
	
		//Compulsory fields.
		if ( stuuser == "" ||
		 	 stupwd == "" ||
		 	 stufname == "" ||
		 	 stulname == "" )
		{
			if (!linebreak)
			{
				errmsg += "\n";
				linebreak = true;
			}				
			errmsg += "\nSTUDENT " + i + ": Not all required fields(*) are entered.";
			result = false;
		}
	}
	
	//Check if there's duplicate user ID entered in all the forms.
	if ( checkDuplicateInArray(userIdArray) )
	{
		errmsg += "\n\nDo not use the same user ID for account creation.";
		result = false;
	}
	
	//Display error if any.
	if (!result)
		alert ("***** Error *****" + errmsg);
	
	return result;	
}


//Check if there's duplicate value in array. True if there is.
function checkDuplicateInArray(arr)
{
	var tmp = new Array();
	
	for (var i=0; i<arr.length; i++)
	{
		for (var j=0; j<tmp.length; j++)
		{
			if (tmp[j] == arr[i])
				return true;
		}		
		tmp[tmp.length] = arr[i];
	}
		
	return false;
}


//Verifies entries.
function checkAcctCreateParent(sUserID, lenMinUser, sFirstName, sLastName, sEmail1, sEmail2, sPwd1, sPwd2, lenMinPwd, sContactNo, sAddr, sPostCode, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var userid = sUserID.trim();
	var fname = sFirstName.trim();
	var lname = sLastName.trim();
	var email1 = sEmail1.trim();
	var email2 = sEmail2.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	var contactno = sContactNo.trim();
	//var state = sState.trim();
	var addr = sAddr.trim();
	var postcode = sPostCode.trim();
	
	//Error if User ID not yet checked.
	if (!bChkId)
	{
		errmsg += "\nPlease check whether user ID and email is available for use.";
		result = false;
	}
	
	//Compulsory fields.
	if ( userid == "" ||
		 fname == "" ||
		 lname == "" ||
		 email1 == "" ||
		 email2 == "" || 
		 pwd1 == "" ||
		 pwd2 == "" ||
		 contactno == "" ||
		 //state == "" ||
		 addr == "" ||
		 postcode == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
		
	//Check passwords.
	if ( pwd1 != pwd2 )
	{
		errmsg += "\nPasswords do not match.";
		result = false;
	}
	else if (pwd1.length < lenMinPwd)
	{
		errmsg = errmsg + "\nPassword must be minimum " + lenMinPwd + " characters.";
		result = false;
	}
	
	//Check that email is valid.
	if (sEmail1 != sEmail2)
	{
		errmsg += "\nEmails do not match.";
		result = false;
	}
	else if ( !checkEmail(sEmail1) )
	{
		errmsg += "\nInvalid email.";
		result = false;
	}
	
	//Display error if any.
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;	
}


//Verify entries for editing parent account.
function checkAcctEditParent(sFirstName, sLastName, sEmail, sPwd1, sPwd2, lenMinPwd, sContactNo, sAddr, sPostCode)
{	
	var result = true;
	var errmsg = '';
	
	var fname = sFirstName.trim();
	
	var lname = sLastName.trim();
	var email = sEmail.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	var contactno = sContactNo.trim();
	var addr = sAddr.trim();
	var postcode = sPostCode.trim();
	
	//Compulsory fields.
	if ( fname == "" ||
		 lname == "" ||
		 email == "" ||
		 contactno == "" ||
		 //state == "" ||
		 addr == "" ||
		 postcode == "" )
	{
		errmsg += "\nNot all required fields are entered.";
		result = false;
	}
	
	if (pwd1 != "" || pwd2 != "")
	{
		if (pwd1 != pwd2)
		{
			errmsg += "\nPasswords do not match.";
			result = false;
		}
		else if (pwd1.length < lenMinPwd)
		{
			errmsg += "\nPasswords must be minimum " + lenMinPwd + " characters.";
			result = false;
		}
	}
	
	//Check that email is valid.
	if ( !checkEmail(sEmail) )
	{
		errmsg += "\nInvalid email.";
		result = false;
	}
	
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
	
}


//Verify entries for editing admin account.
function checkAcctEditAdmin(sName, sEmail, sPwd1, sPwd2)
{
	var result = true;
	var errmsg = '';
	
	var name = sName.trim();
	var email = sEmail.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	//Compulsory fields.
	if ( name == "" ||
		 email == "")
	{
		errmsg += "\nName and email are required.";
		result = false;
	}
	
	if ( (pwd1 != "" || pwd2 != "") &&
		 (pwd1 != pwd2) )
	{
		errmsg += "\nPasswords do not match.";
		result = false;
	}
	
	//Check that email is valid.
	if ( !checkEmail(sEmail) )
	{
		errmsg += "\nInvalid email.";
		result = false;
	}
	
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
	
}

//Verify entries for creating admin account.
function checkAcctCreateAdmin(sUserID, sName, sEmail, sPwd1, sPwd2, bChkId)
{
	var result = true;
	var errmsg = '';
	
	var userid = sUserID.trim();
	var name = sName.trim();
	var email = sEmail.trim();
	var pwd1 = sPwd1.trim();
	var pwd2 = sPwd2.trim();
	
	//All fields are compulsory.
	if ( userid == "" ||
		 name == "" ||
		 email == "" ||
		 pwd1 == "" ||
		 pwd2 == "" )
	{
		errmsg += "\nAll fields are required.";
		result = false;
	}
	
	//Error if User ID not yet checked.
	if (!bChkId)
	{
		errmsg += "\nPlease check whether user ID is available for use.";
		result = false;
	}
	
	if ( pwd1 != pwd2 )
	{
		errmsg += "\nPasswords do not match.";
		result = false;
	}	
	else if ( pwd1.length < 4 )
	{
		errmsg += "\nPasswords must be at least 4 characters long.";
		result = false;
	}
	
	//Check that email is valid.
	if ( !checkEmail(sEmail) )
	{
		errmsg += "\nInvalid email.";
		result = false;
	}
		
	
	if (!result)
		alert ("Error:" + errmsg);
	
	return result;
}


//Check if email is correct. False if not correct.
function checkEmail(sEmail) 
{
   return (sEmail.lastIndexOf(".") > 2) && (sEmail.indexOf("@") > 0);
}


//Redirect to indicated web address.
function redirect(sAddr)
{
	window.location = sAddr;
}


/**** AJAX ****/

function GetXmlHttpObject()
{
	var xmlHttp = null;
	
	try
  	{
  		// Firefox, Opera 8.0+, Safari
  		xmlHttp = new XMLHttpRequest();
  	}
	catch (e)
  	{
  		// Internet Explorer
 		try
    	{
    		xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
    	}
  		catch (e)
    	{
    		xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    	}
  	}

	return xmlHttp;
}


/**** String trim function *****/
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}

function trim(stringToTrim) {
	return stringToTrim.replace(/^\s+|\s+$/g,"");
}
function ltrim(stringToTrim) {
	return stringToTrim.replace(/^\s+/,"");
}
function rtrim(stringToTrim) {
	return stringToTrim.replace(/\s+$/,"");
}


//Strip new line (\n and \r\n) from the front and end of the string.
function trimNewLine(stringToTrim) 
{
	var tmp = stringToTrim.replace(/^\r\n+|\r\n+$/g,"");	//Strip "\r\n" if available.
	return tmp.replace(/^\n+|\n+$/g,"");					//Strip "\n" if available.
}


//Check that value is numeric. Can contain decimal points and negative signs too.
function isNumeric(value) 
{
	if (value == null || value == '' || !value.toString().match(/^\d*\.?\d*$/))
		return false;
	
	return true;
}


//Return the index in an array. Returns -1 if not found.
function indexInArray(aArray, sSearchFor)
{
	for (var i=0; i<aArray.length; i++)
	{
		if (aArray[i] == sSearchFor)
			return i;
	}
	
	return -1;
}


//Function that returns an array of elements that has the specified class name.
//elmPar is the parent element that contains the elements with the class ("document" if root), sClassTag is the tag (eg. div, "*"), sClassName is the class name to look for (eg. "pricePaid").
function k_getElementsByClassName(elmPar, sClassTag, sClassName)
{
	var elmArray = new Array();
	
	var elmTmp = elmPar.getElementsByTagName(sClassTag);
	
	for (var i=0; i<elmTmp.length; i++)
	{
		if (elmTmp[i].className == sClassName)
			elmArray.push(elmTmp[i]);
	}
	
	return elmArray;
}
