var sUrl=window.location.href;
var sTitle = document.title;
var sImageBase = "";
if (sUrl.search("students/") != -1 || sUrl.search("demoteam") != -1 || isStudentInfoPage() || isStorePage() || isPhotoPage())
	sImageBase = "../";	
var sURLBase = sImageBase;

sImageBase += "images/";
//alert(sUrl+"  :    "+sImageBase);

//	TODAY'S DATE		
var gdateNow = new Date();
var gdateEndClass = new Date();
	//	TEMP!! ADJUST DATE FOR TESTING
//	var date2 = gdateNow.getDate()-3;
//	gdateNow.setDate(date2);

//	USED TO START STUDENT OFF WITH INITIAL PROGRESS
var giGuessProgress=0;
var bForceSave = false;

var giOverallProgress = 0.0;
var giLevelRequired=30;
var gDateRecentClass;
var gbAllowRecordsChange = false;
var giProgressDone=0;
var giIntervalID=0;
var giUpdateID=0;
var bAnimateProgress=true;
var giShowLevel=0;
var giAllowDayLimit = 7;			//	THEY NEED TO ATTEND A CLASS WITHIN LAST 7 DAYS TO LOG PROGRESS

var giLevelWidth=180;
var gsExtra="";
var gsLessonToSend="";

var gbGoUserPageOnLogin=true;
var gbNowPlan = false;
var gbTestPlan = false;

//	PRELOAD IMAGES
var nor_menu1 = new Image(210,33);
var hi_menu1 = new Image(210,33);
nor_menu1.src = sImageBase+"academy_1.jpg"
hi_menu1.src = sImageBase+"academy_2.jpg"

var nor_menu2 = new Image(210,33);
var hi_menu2 = new Image(210,33);
nor_menu2.src = sImageBase+"schedule_1.jpg";
hi_menu2.src = sImageBase+"schedule_2.jpg";

var nor_menu3 = new Image(210,33);
var hi_menu3 = new Image(210,33);
nor_menu3.src = sImageBase+"levels_1.jpg";
hi_menu3.src = sImageBase+"levels_2.jpg";

var nor_menu4 = new Image(210,33);
var hi_menu4 = new Image(210,33);
nor_menu4.src = sImageBase+"history_1.jpg";
hi_menu4.src = sImageBase+"history_2.jpg";

var nor_menu5 = new Image(210,33);
var hi_menu5 = new Image(210,33);
nor_menu5.src = sImageBase+"store_1.jpg";
hi_menu5.src = sImageBase+"store_2.jpg";

var nor_menu6 = new Image(210,33);
var hi_menu6 = new Image(210,33);
nor_menu6.src = sImageBase+"links_1.jpg";
hi_menu6.src = sImageBase+"links_2.jpg";

var giStartPercentOverall = 0;
var giStartTotalPracticed = 0;


var gsAttendanceStatus = new Array();
gsAttendanceStatus[0]="";
gsAttendanceStatus[1]="";

var giNextClassID = new Array();
var giNextClassIndex = new Array();
var gsUpcomingClass = new Array();	
var giClassChanged=0;
var gbClassChanged=true;
var gdateStart = new Date();	
var gdateNextFinish = new Date();
var giClassDurationMinutes=0;

var giClassIndex = -1;
var giClassID = 0;
var dateIncrement = 1;

var xmlhttp;
var xmlhttp2;
var xmlhttp3;
var xmlhttp4;
var xmlhttp5;
var xmlhttp6;
var xmlhttp7;
var xmlhttp8;

var start;
var sModifyUserID;

//	STUDENT DATA
var gsUserID;
var gsFirstName;
var gsLastName;
var giLevel=0;
var gsAvatarURL;
var giLevelInProgress=0;

//	MASTER DATA
var gsMasterFirstName = "";
var gsMasterLastName = "";
var gsMasterAvatarURL = "";
var gsMasterUserID = "";
var giMasterLevel = 0;
var giMasterLevelInProgress=10;
var giMasterOverallProgress = 0;
			
var iRequired=new Array();
var iPracticed=new Array();
var iPracticedToday=new Array();
var gsPractice=new Array();

var giTotalPracticed=0;
var giTotalRequired=0;

//var gPracticeColors[]=["","LightSteelBlue","DarkSalmon"];
var gPracticeColors=new Array("","LightSteelBlue","DarkSalmon");

//	LOAD COOKIES WITH LOGIN INFO
function loadLoginData ()
{
	//	LOOK FOR MASTER LOGIN
	gsMasterFirstName=getCookie("masterfirstName");
	gsMasterLastName=getCookie("masterlastName");
	gsMasterAvatarURL=getCookie("masterAvatarURL");
	var sLevel = getCookie("masterlevel");
	giMasterLevel=getNumber(sLevel);
	gsMasterUserID=getCookie("masteruserID");
	giMasterOverallProgress = getNumber(getCookie("masterprogress"));				

	//	ARE LOGIN CREDENTIALS IN QUERY STRING?
	var sQuery = sUrl.split("?");
	
	//	IS THERE A PARAMETER TO SHOW LESSON PLAN A SPECIAL WAY?
	if (isLessonPlan() && sQuery[1] && sQuery[1] != "")
	{
		//	SHOW CURRENT ACTIVE LESSON PLAN?
		var sParam = getQueryParam(sQuery[1],"plan");
		if (sParam=="nowPlan")
			gbNowPlan = true;
		
		//	DO TEST OF ACTIVE ARROW?
		var sParam2 = getQueryParam(sQuery[1],"test");
		if (sParam2=="now")	
			gbTestPlan = true;
		sQuery[1]="";
	}
	
	//	ATTENDANCE & LOGGING IN AS SEIMU?
	if (isAttendancePage() && sQuery[1] && sQuery[1] != "")
	{
		gsFirstName=getQueryParam(sQuery[1],"firstName");
		gsUserID=getQueryParam(sQuery[1],"id");
		actualDoLogin(gsFirstName, gsUserID, false);
	}
	else if (sQuery[1] && sQuery[1] != "")
	{
		gsFirstName=getQueryParam(sQuery[1],"firstName");
		gsUserID=getQueryParam(sQuery[1],"id");
		actualDoLogin(gsFirstName, gsUserID, true);
	}
	else
	{
		gsFirstName=getCookie("firstName");
		gsLastName=getCookie("lastName");
		gsAvatarURL=getCookie("AvatarURL");
		sLevel = getCookie("level");
		giLevel=getNumber(sLevel);
		if (isNaN(giLevel) && gsFirstName && gsFirstName!="")
		{
			giLevel = 0;
			logout();
			return;
		}	
		giLevelInProgress = giLevel+1;
		if (giLevelInProgress > 10)
			giLevelInProgress = 10;
		gsUserID=getCookie("userID");
		giOverallProgress = getNumber(getCookie("progress"));
		checkForProgressGuess();
		if (isNaN(giOverallProgress))
		{
			giOverallProgress = 0;
			setCookie("progress",giOverallProgress);
		}
		
		//	HIT SERVER TO DO LOGIN IN CASE PROGRESS/LEVEL HAS CHANGED
		if (!isLoggedInAsSifu() && gsFirstName && gsFirstName!="" && gsUserID!="")
			actualDoLogin(gsFirstName, gsUserID, false);
	}
}

//	IF THERE IS NEGATIVE PROGRESS, IT MEANS IT'S A PROGRESS GUESS FOR INACTIVE STUDENT
//	THEREFORE, WE SET FLAGS TO FORCE SAVE OF ACTUAL PROGRESS ON FIRST VIEW OF ACTUAL PROGRESS PAGE
function checkForProgressGuess ()
{
	if (giOverallProgress < 0)
	{
		setCookie("progress",giOverallProgress);
		giOverallProgress = -giOverallProgress;
		giGuessProgress=giOverallProgress;
//		alert ("now make progress at "+giGuessProgress/10+"% "+"overall="+giOverallProgress);
		bForceSave = true;
		return true;
	}
	else
		return false;
}

//	SIFU OPENS SPECIFIED STUDENT'S PAGE
function openStudentPage (id, sFirstName, level)
{
	//	THIS IS NOT ACCESSIBLE UNLESS SIFU IS LOGGED IN
	if (!isLoggedInAsSifu())
		goto_AcademyPage();	
	
	var sGoURL = "http://www.dynamicdefense.ca/studentRedirect.htm?firstName="+sFirstName+"&id="+id;
	window.open(sGoURL);
	//	LOGIN AS THE SPECIFIED USER	
	//actualDoLogin(sFirstName, id);	
}

//	SETUP FOR ANY PAGE
function stdLoad (sPage)
{
	loadLoginData();
			
	if (sPage!='index')
	{
		if (isLoggedIn())
			showLoggedIn();
		else
			showLoginBtn();
			
		Nifty("div#logged_in","transparent");
		
		//	SHOW LINK TO PERFORMANCE TRACKER HELP
		if (isStudentInfoPage() && document.getElementById("trackerHelp"))
			document.getElementById("trackerHelp").style.visibility='visible';	
	}	
	
	//	IF THEY ARE NOT LOGGED IN, BOOT THEM TO MAIN ACADEMY PAGE
	if (pageRequiresLogin() && !isLoggedIn())
	{
		goto_AcademyPage();
	}	
}

//	EXECUTE WHEN STATS PAGE LOADED
function statsPageLoaded ()
{
	loadLoginData();
}
	
//	EXECUTE WHEN SIFU PAGE LOADED
function sifuPageLoaded ()
{
	loadLoginData();

	//	FOR STUDENT LIST, MUST BE LOGGED IN
	if (isStudentList())
	{
		if (!isLoggedIn())
			goto_AcademyPage();
	}
	//	FOR SIFU COMMAND PAGE, MUST BE SIFU
	else if (!isLoggedInAsSifu())
		 goto_AcademyPage();
		 
	reloadSifuPage();
}
	
//	EXECUTE WHEN LESSON PLAN PAGE LOADED
function lessonPlansLoaded ()
{
	loadLoginData();
	determineClassForPlan(-1);
	determineThisClass();
}
	
//	EXECUTE WHEN ATTENDANCE PAGE LOADED
function attendanceLoaded ()
{
	//alert("attendanceLoaded");
	loadLoginData();
	determineThisClass();
}
	
//	SETUP FOR STUDENT'S PERSONAL PAGE
function handleLoad ()
{
	stdLoad();

	//	ROUNDED DIVS
	Nifty("div.studentInfo","transparent");
//	Nifty("div.welcome","transparent");
	
	//	LOAD LIVE DATA
	if (isSkillPage())
	{		
		if (!isStatsPage())
			loadStudentData();	
	}
}

//	PERSONAL STATS PAGE?
function isStatsPage ()
{
	if (sTitle.search("Stats") != -1)
		return true;
	else
		return false;
}

function isPhotoPage ()
{
	if (sTitle.search("Photo") != -1)
		return true;
	else
		return false;
}

function isStorePage ()
{
	if (sTitle.search("Martial Arts Store") != -1)
		return true;
	else
		return false;
}

//	ATTENDANCE PAGE & LOGGED IN AS SEIMU JANE?
function isActualAttendancePage()
{
	return (isLoggedInAsSeimu() && isAttendancePage());
}

//	ATTENDANCE PAGE?
function isAttendancePage()
{
	if (sTitle.search("Class Attendance") != -1)
		return true;
	else	
		return false;
}

//	STUDENT INFO PAGE?
function isStudentInfoPage ()
{
//alert(sTitle);
	if (isSkillPage() || sTitle.search("Student Info") != -1)
		return true;
	else	
		return false;
}

//	STUDENT LIST?
function isStudentList ()
{
	if (sTitle.search("Student List") != -1)
		return true;
	else
		return false;
}

//	LESSON PLAN PAGE?
function isLessonPlan ()
{
	if (sTitle.search("Lesson Plan") != -1)
		return true;
	else
		return false;
}

//	TOGGLE VISIBILITY OF AN ELEMENT
function toggleVisible (divid)
{
	var sAnchor = divid+"_a";
	
	//	ELEMENT DOESN'T EXIST?
	if (!document.getElementById(divid))
		return;

	//	SHOW IT
  if (document.getElementById(divid).style.display == 'none')
  {
    document.getElementById(divid).style.display = 'block';
    
    //	CHANGE ANCHOR TEXT
    if(document.getElementById(sAnchor))
		{
			var sText = getText(sAnchor);
			sText=sText.replace("[+]","[-]");
			setText(sAnchor,sText);
		}
  }
  //	HIDE IT
  else
  {
    document.getElementById(divid).style.display = 'none';
    
    //	CHANGE ANCHOR TEXT
    if(document.getElementById(sAnchor))
		{
			var sText = getText(sAnchor);
			sText=sText.replace("[-]","[+]");
			setText(sAnchor,sText);
		}
  }
}

//	IS THIS PAGE A STUDENT SKILL PAGE?
function isSkillPage ()
{
	if (sTitle.search("Wing Chun Skills") != -1)
		return true;
	else	
		return false;
}

//	SET TEXT FOR AN ELEMENT
function setText (sElement, sText)
{
	if (document.getElementById(sElement).textContent)
		document.getElementById(sElement).textContent = sText;
	else
		document.getElementById(sElement).innerText = sText;
}

//	GET TEXT FROM AN ELEMENT
function getText (sElement)
{
	if (document.getElementById(sElement).textContent)
		return document.getElementById(sElement).textContent;
	else
		return document.getElementById(sElement).innerText;
}

// Replaces all instances of the given substring.
String.prototype.replaceAll = function(
strTarget, // The substring you want to replace
strSubString // The string you want to replace in.
){
var strText = this;
var intIndexOfMatch = strText.indexOf( strTarget );
 
// Keep looping while an instance of the target string
// still exists in the string.
while (intIndexOfMatch != -1){
// Relace out the current instance.
strText = strText.replace( strTarget, strSubString )
 
// Get the index of any next matching substring.
intIndexOfMatch = strText.indexOf( strTarget );
}
 
// Return the updated string with ALL the target strings
// replaced out with the new substring.
return( strText );
}

//	ADD CLICK HANDLER TO CLASS OF OBJECTS
function addClick(className) 
{
  var elements = getElementsByClassName(document, className);
	n = elements.length;
//	alert("found "+n+" elements");
	for (var i = 0; i < n; i++) 
	{
    var e = elements[i];
	//	alert("adding for"+e);
		AddEventListener(e, "click", handleClick, false);	
  }
}

//	IS ELEMENT VISIBLE OR NOT?
function isVisibleElement (e)
{
	if (e.style.visibility == 'hidden')
		return false;
	else
		return true;
}

//	GET TYPE/ID OF ELEMENT
function indirectTypeAndID (e)
{
	var targ;
	if (!e) 
		var e = window.event;
	if (e.target) 
		targ = e.target;
	else if (e.srcElement) 
		targ = e.srcElement;
	if (targ.nodeType == 3) // defeat Safari bug
		targ = targ.parentNode;
	
	return getTypeAndID(targ);
}
function getTypeAndID (e)
{
	return e.id.split("_");	
}

function handleClick (e)
{
	var itemInfo=indirectTypeAndID(e);
	var type = itemInfo[0];
	var id = itemInfo[1];
//	alert(type+" with id "+id+" was clicked");
	switch (type)
	{
		case "addSkill": addSkill(id); break;
		case "dropSkill": dropSkill(id); break;
	}
}

//	REMOVE LEADING OR TRAILING SPACES
function trimSpaces (sString)
{
 return sString.replace(/^\s+|\s+$/g, '');
}

//	GET STRIPPED NAME OF THIS SKILL
function getSkill (id)
{
	var sCell="skill_"+id;
	sSkill = getText(sCell);

	// if (sSkill.search("Intermediate") != -1)
		// alert(sSkill);
	
	//	TRIM SPACES WE DON'T NEED
	sSkill = trimSpaces(sSkill);
	
//	sSkill = sSkill.replace(/^\d/, '');

	//	TRIM CARRIAGE RETURNS
	sSkill = sSkill.replace(/[\r\n]+/g, '');
	sSkill = sSkill.replace(/\t+/g, ' ');
 
	//	OTHER EXTRANEOUS CHARACTERS
	sSkill = sSkill.replace('.', '');
	sSkill = sSkill.replace('-', '');
	
	//	TRIM OFF SPACES AFTER LOOKING FOR HYPHENS
	sSkill = trimSpaces(sSkill);
	
	//	REPLACE ANY DOUBLE SPACES WITH SINGLE SPACES
	sSkill = sSkill.replaceAll("  "," ");
	
	// if (sSkill.search("Intermediate") != -1)
		// alert(sSkill);
	
	return sSkill;
}

function AddEventListener(element, eventType, handler, capture)
{
	if (element.addEventListener)
		element.addEventListener(eventType, handler, capture);
	else if (element.attachEvent)
		element.attachEvent("on" + eventType, handler);
}

//	GET ALL ELEMENTS OF SAME CLASS
function getElementsByClassName(node,classname) 
{
  if (node.getElementsByClassName) 
	{ // use native implementation if available
    return node.getElementsByClassName(classname);
  } 
	else 
	{
    return (function getElementsByClass(searchClass,node) 
		{
        if ( node == null )
          node = document;
        var classElements = [],
            els = node.getElementsByTagName("*"),
            elsLen = els.length,
            pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"), i, j;

        for (i = 0, j = 0; i < elsLen; i++) {
          if ( pattern.test(els[i].className) ) {
              classElements[j] = els[i];
              j++;
          }
        }
        return classElements;
    })(classname, node);
  }
}

//	SHOW BTN TO ALLOW LOGIN
function showLoginBtn ()
{
//	alert("showLoginBtn");
	if (!document.getElementById("loginBtn"))
		return;
		
	document.getElementById("loginBtn").style.visibility='visible';
	document.getElementById("show_logged_in").style.visibility='hidden';
}

//	ATTEMPT TO OPEN A LEVEL SKILL PAGE
function goto_level (iTheLevel)
{
	//	CAN'T SEE LEVELS WITHOUT LOGGING IN
	if (!isLoggedIn())	
	{
		alert("Please login to access this page.\nOnly current active students of Dynamic Defense can view the interactive grading plans for each level.");
		return;   
	}
	
	//	ATTEMPT TO LOOK PAST ONE'S OWN LEVEL?
	//	ALLOW THEM TO LOOK ONE LEVEL PAST THEIR OWN
	var iNeededLevel = iTheLevel-2;
	if (giLevel < iNeededLevel)
	{		
		alert("The worksheet for level "+iTheLevel+" isn't unlocked until you are level "+iNeededLevel+".");
		return;
	}
	
	openLevelPage(iTheLevel);
}

//	OPEN SPECIFIC LEVEL WORKSHEET
function openLevelPage (iTheLevel)
{
//	if (isNaN(iTheLevel))
//	{
//		logout();
//		return;
//	}
		
	var sThePage = "skills/level"+iTheLevel+".htm";
	var sPage = sURLBase+sThePage;
	
	//	NOT ALREADY THERE?
	if (sUrl.search(sThePage) == -1)
		window.location.href = sPage;
//	else
//		alert(sURL+"...."+sPage);
}

//	GO TO USER'S PERSONAL PAGE
function goto_userPage ()
{
	if (gsFirstName == "Sifu Bill")
	{
		window.location.href = sURLBase+"sifu.html";	
		return;
	}
		
	var iTheLevel = giLevel+1;
	if (iTheLevel > 10)
		iTheLevel = 10;
	openLevelPage(iTheLevel);
}

//	GO TO ACADEMY PAGE
function goto_AcademyPage ()
{
	//	JUST TESTING IN FRONTPAGE?
	if (sUrl.search("dynamicdefense.ca") == -1)
		return;

	sPage = sURLBase+"academy.htm";
	window.location.href = sPage;
}

//	IS USER LOGGED IN NOW AS SIFU?
function isLoggedInAsSeimu ()
{
	return (isLoggedIn() && gsFirstName=="Jane");
}

//	IS USER LOGGED IN NOW AS SIFU?
function isLoggedInAsSifu ()
{
	if (gsMasterFirstName && gsMasterFirstName=="Sifu Bill")
		return true;
	else 
		return false;
}

//	IS USER LOGGED IN NOW?
function isLoggedIn ()
{
	if (gsFirstName&& gsFirstName!="")
		return true;
	else
	return false;
}

//	DOES VIEWING THIS PAGE REQUIRE A VALID LOGIN?
function pageRequiresLogin ()
{	
	if (!isPhotoPage() && (isStudentInfoPage() || isStudentList()))
		return true;
	else	
		return false;
}

//	SHOW WELCOME TO PROGRESS TRACKER IF NOT SHOWN YET
function checkShowProgressWelcome ()
{
//	if (isLoggedInAsSifu())
//		return;
	
	//	HAVE WE SHOWN WELCOME FOR THIS LEVEL? IF NOT, THEN SHOW IT ONCE & SET COOKIE TO NOT DO IT AGAIN	
	var iProgressWelcomeLevel = getCookie("showWelcome");
	if (!isLoggedInAsSifu() && iProgressWelcomeLevel != giLevelInProgress)
	{
		showProgressWelcome();
	}	
}


//	SHOW WELCOME TO PROGRESS TRACKER
function showProgressWelcome ()
{
	var sWelcome = "Hi, "+gsFirstName+"!";
	var sWelcome2 = "Welcome to your personal Dynamic Defense Progress Tracker. ";
	sWelcome2 += "It has information and tools to help you progress to level "+giLevelInProgress+".";
	
	setText("welcomeProgressText", sWelcome);
	setText("welcomeProgressText2", sWelcome2);

	var sDiv = "welcomeProgressPage";
	document.getElementById(sDiv).style.position='absolute';
	document.getElementById(sDiv).style.top = 8;
	document.getElementById(sDiv).style.right = 6;
	document.getElementById(sDiv).style.marginRight = 1;
	document.getElementById(sDiv).style.visibility='visible';
}

//	CLOSE WELCOME SCREEN SET COOKIE TO NOT SHOW AGAIN UNTIL NEXT LEVEL
function closePerformanceWelcome ()
{
	var sDiv = "welcomeProgressPage";
	document.getElementById(sDiv).style.visibility='hidden';
	setCookie("showWelcome",giLevelInProgress);
}

//	SHOW LOGIN DIV
function showLoginDialog() 
{	
	//	ALREADY LOGGED IN? THEN SKIP TO MAIN ACADEMY PAGE AS LOGGED IN USER
	if (isLoggedIn())
		goto_AcademyPage();
	else
	{
//alert("showLoginDialog");
		document.getElementById("loginFailed").style.visibility='hidden';
		document.getElementById("login").style.position='absolute';
		document.getElementById("login").style.top = 8;
		document.getElementById("login").style.right = 6;
		document.getElementById("login").style.marginRight = 1;
		document.getElementById("login").style.visibility='visible';
		document.getElementById("username").focus();
	}
}
function closeLogin() 
{
	document.getElementById("login").style.visibility='hidden';
}

//	GET THE REQUIRED REPS TO PRACTICE THIS SKILL FOR THIS LEVEL
function getRequired (sSkill)
{
	return giLevelRequired;
		
	//	USE giLevelInProgress & sSkill TO LOAD # FROM DBASE
//	return 20;
}

//	GET THE REQUIRED REPS TO PRACTICE THIS SKILL FOR THIS LEVEL
function getPracticeRecords ()
{
	//	CALL INTO SERVER
//	var sSkillEncoded = escape(sSkill);
	xmlhttp5 = getRequest();
	if (!xmlhttp5)
		return;
	
	//	REQUEST PRACTICE DATA
	var sRequest = "../getSkill.php?userID="+gsUserID+"&level="+giLevelInProgress+"&uniq="+Math.random();
	 
	// if (sSkill.search("round punch") != -1)
//		 alert(sSkill+" : "+sRequest);
	xmlhttp5.open("GET",sRequest,true);
	xmlhttp5.onreadystatechange = receivePracticeRecords;
	xmlhttp5.send(null);
}

//	AJAX RECEIVE REQUIRED REPS & PRACTICE RECORDS
function receivePracticeRecords ()	
{
	if (xmlhttp5.readyState==4 && xmlhttp5.status==200)
	{
		//	PROCESS RESPONSE		
		var sResponse = xmlhttp5.responseText;	
		sResponse = trimSpaces(sResponse);	
		
		//	GET ARRAY OF SKILLS PRACTICED
		gsPractice = sResponse.split(";");	

		//	DO WE HAVE VALID PRACTICE RECORDS? IF NOT, THEN BAIL ON PAGE ENTIRELY
		if (gsPractice[0] != gsUserID)
		{
			goto_AcademyPage();
			return;
		}
		
		//	REQUIRED SKILL REPS AT THIS LEVEL
		var sReps = gsPractice[1];
		giLevelRequired = getNumber(sReps);
		if (isNaN(giLevelRequired))
		{
			goto_AcademyPage();
			return;
		}
		
		//	PROCESS STUDENT RECORDS
		finishLoadStudentData();
	}
}

//	GET THE # OF TIMES THIS SKILL HAS BEEN PRACTISED
function getPractice (id, sSkill)
{
	//	IF LOOKING AT A PREVIOUS LEVEL, SHOW ALL SKILLS COMPLETE
	if (giLevelInProgress <= giLevel)
		return iRequired[id];
			
	//	LOOK THROUGH ARRAY OF PRACTICE RECORDS FOR MATCH
	var sSkillEncoded = escape(sSkill);
	
	var iPracticed = 0;
	var n=gsPractice.length;
	for (var i=5; i<n; i+=2)
	{
		// if (id==3 || sSkill.search("parallel") != -1)
			// alert(sSkill+" : "+sSkillEncoded+" : "+gsPractice[i]);
			
		if (gsPractice[i] == sSkill || gsPractice[i] == sSkillEncoded)
		{
			iPracticed = getNumber(gsPractice[i+1]);
			return iPracticed;
		}
	}
	
	//	ARE WE GUESSING AT STUDENT'S PROGRESS?
	if (giGuessProgress)
		iPracticed=Math.round(iRequired[id]*giGuessProgress/1000);
	return iPracticed;
}

//	HIDE CERTAIN ITEMS (HEADERS FOR A GROUP OF TRAINING ITEMS)
function hideUnusedSkills ()
{
//alert(giLevelInProgress);
	switch (giLevelInProgress)
	{
		case 1: 
			hideSkill(5);
			hideSkill(9);
			break;
		case 2: 
			hideSkill(6);
			hideSkill(10);
			break;
		case 3: 
			hideSkill(6);
			hideSkill(13);
			hideSkill(18);
			break;
		case 4: 
			hideSkill(3);
			hideSkill(8);
			hideSkill(15);
			hideSkill(22);
			break;
		case 5: 
			hideSkill(9);
			hideSkill(17);
			hideSkill(23);
		break;
		case 6:
			hideSkill(8);
			hideSkill(14);
			hideSkill(25);
			hideSkill(32);
			break;
		case 7:
			hideSkill(3);
			hideSkill(7);
			hideSkill(22);
			hideSkill(33); 
			break;
		case 8: 
			hideSkill(5);
			hideSkill(10);
			hideSkill(26);
			hideSkill(35);
			break;
		case 9: 
			hideSkill(3);
			hideSkill(15);
			break;
		case 10: 
			break;
	}
	
}

//	HIDE UNUSED ELEMENTS
function hideSkill (iSkill)
{
	var sElement = "practice_"+iSkill;
	document.getElementById(sElement).style.visibility='hidden';
	sElement = "addSkill_"+iSkill;
	document.getElementById(sElement).style.visibility='hidden';
	sElement = "dropSkill_"+iSkill;
	document.getElementById(sElement).style.visibility='hidden';
	sElement = "ready_"+iSkill;
	document.getElementById(sElement).style.visibility='hidden';
	sElement = "skill_"+iSkill;
	document.getElementById(sElement).className = "skillHeader";
}

//	 CONFIRM SKILL UPLOADED
function confirmSkill ()
{
	if (xmlhttp4.readyState==4 && xmlhttp4.status==200)
	{
		var sResponse = xmlhttp4.responseText;	
	//	alert ("skill:("+sResponse+")");
		sResponse = sResponse.replace(/^\s+|\s+$/g, '');
	}
}

//	LOAD STUDENT DATA
function loadStudentData ()
{
	//	GET LEVEL FROM DOCUMENT
	if (document.getElementById("level"))
	{
		var sLevel=getText("level");
		sLevel = trimSpaces(sLevel);
		sL = sLevel.split(" ");	
		giLevelInProgress=getNumber(sL[1]);
		
		//	DO WE NEED TO SHOW WELCOME TO PROGRESS PAGE?
		checkShowProgressWelcome ();
	}
	else
	{
		describeStudent();
		return;
	}
	
	//	INVALID LEVEL TO VIEW? 
	if (giLevel < giLevelInProgress-1)
	{
		goto_AcademyPage();
		return;
	}
	
//	alert(sLevel+" : "+sL[1]+" : "+giLevelInProgress);
	
	//	HIDE CERTAIN ITEMS (HEADERS FOR A GROUP OF TRAINING ITEMS)
	if (document.getElementById("level"))
		hideUnusedSkills();
	
	//	LOAD PRACTICE RECORDS
	getPracticeRecords();
}
	
//	FINISH LOADING STUDENT DATA AFTER AJAX CALLBACK
function finishLoadStudentData ()
{	
	//	GET DATA ON UPCOMING CLASSES
	determineThisClass();
		
	//	NO ATTENDANCE RECORD FOR THIS STUDENT? 
	if (gsPractice.length < 4)
		gbAllowRecordsChange = false;
	else
	{	
		//	DATE OF MOST RECENT ATTENDED CLASS
		var sDate = gsPractice[3].split("-");
		gDateRecentClass = new Date(sDate[0],sDate[1]-1,sDate[2]);
		var dateAllowChanges = new Date();
		var date2 = dateAllowChanges.getDate()-giAllowDayLimit;
		dateAllowChanges.setDate(date2);
		
		//	DATE
		if (isLoggedInAsSifu() || gDateRecentClass > dateAllowChanges)
		{
			gbAllowRecordsChange = true;
			//	EVENT HANDLERS TO CHANGE PRACTICE RECORDS 
			addClick("addSkill");
			addClick("dropSkill");
	//		alert ("student attended recently, practice records can be changed");
		}
		else
		{	
//			alert(gDateRecentClass.toString()+" : "+dateAllowChanges.toString());
			gbAllowRecordsChange = false;
	//		alert ("NO CHANGES ALLOWED: last attended :"+gDateRecentClass+"\n\n need to attend after "+dateAllowChanges);
		}	
	}
	
	//	SKILLS RECOMMENDED TO PRACTICE
	setText("suggestedPractice",gsPractice[4]);
		
	//	FOR EACH SKILL, GET # OF TIMES PRACTICED & REQUIRED
	var elements = getElementsByClassName(document, "practice");
	n = elements.length;
	
//	alert("found "+n+" elements");
	for (var i=0; i<n; i++) 
	{
    var e = elements[i];
		var itemInfo=getTypeAndID(e);
		var id = itemInfo[1];
		var sSkill = getSkill(id);
		
		iPracticedToday[id]  = 0;
		if (isVisibleElement(e))
		{
			iRequired[id] = getRequired(sSkill);
			iPracticed[id] = getPractice(id, sSkill);
			updateSkill(id, 0);
		}
		//	HIDDEN ELEMENTS DON'T NEED TO BE COUNTED (SUCH AS HEADERS FOR A GROUP OF SKILLS)
		else
		{
			iRequired[id] = 0;
			iPracticed[id] = 0;
		}		
	}
	
	//	DESCRIBE STUDENT
	describeStudent();
}

//	DESCRIBE STUDENT
function describeStudent ()
{
	setText("myFirstName",gsFirstName);
	setText("myLastName",gsLastName);
	setText("myLevel","Level "+giLevel);

//	var sLevelImg = "url(http://www.dynamicdefense.ca/images/gradient-"+giLevel+".png)";
	var sLevelImg = "url("+sURLBase+"images/gradient-"+giLevel+".png)";
	document.getElementById("myInfo").style.backgroundImage=sLevelImg;
	
	//	MAKE TEXT WHITE?
	if (giLevel > 5)
	{
		document.getElementById("myFirstName").style.color = 'White';
		document.getElementById("myLastName").style.color = 'White';
		document.getElementById("myLevel").style.color = 'White';
		document.getElementById("percent").style.color = 'White';		
	}
	document.getElementById("myImgAvatar").src=sURLBase+gsAvatarURL;
	
	if (document.getElementById("smallAvatar"))
		document.getElementById("smallAvatar").src=sURLBase+gsAvatarURL;
		
	//	NOW DESCRIBE OVERALL PROGRESS
	describeOverall(true);
	hideLoadingDiv();
}

//	ONCE WE'RE FULLY LOADED, HIDE THE LOADING DIV
function hideLoadingDiv ()
{
	document.getElementById("loading").style.visibility = 'hidden';
}

//	HIDE AN ELEMENT & REMOVE FROM PAGE FLOW OF HTML
function hideElement (sElement)
{
	if (document.getElementById(sElement))
		document.getElementById(sElement).style.display = 'none';
}

//	SHOW AN ELEMENT 
function showElement (sElement)
{
	if (document.getElementById(sElement))
		document.getElementById(sElement).style.display = 'inline';
}

//	UPDATE ONE SKILL
function updateSkill (id, iClicked)
{
	//	FORCING SAVE OF DATA?
	if (bForceSave)
		iClicked = 1;

	//	HOW MANY PRACTICED TODAY?
	var sSkillCell = "skill_"+id;
	
	//	ADDING AFTER 2 REPS TODAY? THEN DISALLOW	
	if (!isLoggedInAsSifu() && iClicked == 1 && iPracticedToday[id] == 2)
		return;
			
	//	PRACTICED/REQUIRED TEXT
	var sPracticed = "practice_"+id;
	document.getElementById(sPracticed).innerHTML = iPracticed[id]+"/"+iRequired[id];
	
	//	STOP LIGHT FOR THIS SKILL
	var sImage = "ready_"+id;
	var percent = iPracticed[id]/iRequired[id];
	var iPercent = 100*percent;
	iPercent = iPercent.toFixed(1);
	var iNeeded = iRequired[id]-iPracticed[id];
	document.getElementById(sImage).src=getPercentImage(iPercent);
	//alert(document.getElementById(sImage).src);
	
	var sDesc = iPercent+"% ready, ";
	if (iNeeded <= 0)
		sDesc += "this skill is good to go!";
	else if (iNeeded ==1)
		sDesc  += "practice one more time for Level "+giLevelInProgress;
	else
		sDesc += "practice "+iNeeded+" more times for Level "+giLevelInProgress;
	setTooltip(sImage, sDesc);
		
	//	ON USER CLICK, CHANGE CELL BACKGROUND COLOR SO USER KNOWS THEY SHOULDN'T CLICK AGAIN
	iPracticedToday[id] = iPracticedToday[id]+iClicked;
	if (iPracticedToday[id] < 0)
		iPracticedToday[id] = 0;
	document.getElementById(sSkillCell).style.backgroundColor = gPracticeColors[iPracticedToday[id]];
	document.getElementById(sSkillCell).style.color = 'Black';
	
	//	TOOLTIP ON BUTTONS
	if (gbAllowRecordsChange && iPracticedToday[id]<2)
		sDesc = "Click to add another practice session for this skill";
	else
		sDesc = "Please attend another class to log more practice";
	setTooltip("addSkill_"+id, sDesc);

	sDesc = "Click to remove a practice session for this skill";
	setTooltip("dropSkill_"+id, sDesc);
		
	//	USER MADE A CHANGE TO PROGRESS MANUALLY? THEN UPDATE DATABASE
	if (iClicked != 0)
		updateSkillInDatabase(id);
}

//	SET TOOLTIP
function setTooltip (sElem,sText)
{
	//	MAKE SURE ELEMENT EXISTS
	if (!document.getElementById(sElem))
		return;
	document.getElementById(sElem).alt=sText;
	document.getElementById(sElem).title=sText;
}

//	 CONFIRM SKILL UPLOADED
function confirmSkill ()
{
	if (xmlhttp4.readyState==4 && xmlhttp4.status==200)
	{
		var sResponse = xmlhttp4.responseText;	
		sResponse = trimSpaces(sResponse);
		
		setText("suggestedPractice",sResponse);	
	}
}

//	USER MADE A CHANGE TO PROGRESS MANUALLY? THEN UPDATE DATABASE
function updateSkillInDatabase (id)
{
	var sSkill = getSkill(id);
	var sSkillEncoded = escape(sSkill);
	xmlhttp4 = getRequest();
	if (xmlhttp4)
	{
//		if (id == 1)
//			alert ("NEW update skill 1: now make progress at "+giGuessProgress/10+"% "+"overall="+giOverallProgress);
		
		var sRequest = "../skill.php?userID="+gsUserID+"&level="+giLevelInProgress+"&skill="+sSkillEncoded+"&practiced="+iPracticed[id]+"&overall="+giOverallProgress+"&uniq="+Math.random();	
//		alert(sRequest);
		xmlhttp4.open("GET",sRequest,true);
		xmlhttp4.onreadystatechange = confirmSkill;
		xmlhttp4.send(null);
	}
	return false;
}

//	DESCRIBE OVERALL PROGRESS 
function describeOverall (bInit)
{
//alert (iRequired[1]+"  "+iPracticed[1]);
	giTotalRequired = 0;
	giTotalPracticed = 0;
	var iNewSkills = 0;
	var sToday;
	var iPercent = giOverallProgress/10;
	if (document.getElementById("overallLevel"))
	{
		n = iRequired.length;
		for (i=0; i<n; i++) 
		{
			if (!isNaN(iRequired[i+1])) 
				giTotalRequired=giTotalRequired+iRequired[i+1];
		}	
		n = iPracticed.length;
		for (i=0; i<n; i++) 
		{
			if (!isNaN(iPracticed[i+1])) 
				giTotalPracticed=giTotalPracticed+iPracticed[i+1];
		}
	//	alert (giTotalPracticed+"  "+giTotalRequired);
		
		var percent = giTotalPracticed/giTotalRequired;
		iPercent = 100*percent;
		iPercent = iPercent.toFixed(1);
		if (bInit)
		{
			giStartPercentOverall = iPercent;
			giStartTotalPracticed = giTotalPracticed;
		}	
		
		//alert (giTotalPracticed+" : "+giStartTotalPracticed);
	
		//	TODAY'S PROGRESS
		var iNewPercent;
		var sSkills;
		iNewSkills = giTotalPracticed-giStartTotalPracticed;
		//alert("sdfsd"+iNewSkills);	
	}
	
	//	LEVEL IS COMPLETE?
	if (giLevel >= giLevelInProgress)
	{
		document.getElementById("todaysProgress").style.color = 'GoldenRod';
///		document.getElementById("todaysProgress").style.backgroundColor = 'DarkGray';
		sToday = "You've already completed all the skills for Level "+giLevelInProgress+", "+gsFirstName+".";
	}
	//	THEY ARE READY TO GRADE
	else if (giOverallProgress >= 1000)
	{
//		alert(giOverallProgress);
		document.getElementById("todaysProgress").style.color = 'MediumBlue';
//		document.getElementById("todaysProgress").style.backgroundColor = 'White';
		sToday = "You've already completed all the skills for Level "+giLevelInProgress+", "+gsFirstName+".";
	}	
	//	ENCOURAGE THEM TO DO SOME SKILL PRACTICE	
	else if (iNewSkills <= 0)
		sToday = "Hey "+gsFirstName+", practice some of the skills below and you'll be at Level "+giLevelInProgress+" before you know it.";
	//	THEY'VE DONE SOME PRACTICE TODAY
	else 
	{
		 if (iNewSkills==1)
			 sSkills = "1 skill";
		 else	
			 sSkills = ""+iNewSkills+" skills";
		 iNewPercent = iPercent-giStartPercentOverall;
		 iNewPercent = iNewPercent.toFixed(1);
		 document.getElementById("todaysProgress").style.color = 'MediumBlue';
		 sToday = "You've practiced "+sSkills+", "+gsFirstName+". That moves you "+iNewPercent+"% closer to Level "+giLevelInProgress+".";
	}

	setText("todaysProgress",sToday);
	
	//	TEXT % DONE
	var sDesc = iPercent+"% of the way to Level "+giLevelInProgress;
	setText("percent",sDesc);

	//	STOP LIGHT ON WHOLE LEVEL
	document.getElementById("myOverallLevel").src=getPercentImage(iPercent);

	updateProgressTooltips(iPercent,0);
	
	//	STORE OVERALL PROGRESS TO SERVER
	var iShowPercent = iPercent*10;
	var iShowOverall = Math.round(iShowPercent);
	
	if (!isNaN(iShowOverall) && (!bInit || giOverallProgress != iShowOverall))
	{	
		giOverallProgress = iShowOverall;
		setCookie("progress",giOverallProgress);
		if (document.getElementById("overallLevel") && !isLoggedInAsSifu())
			document.getElementById("overallLevel").src=getPercentImage(giOverallProgress/10);
		updateProgressTooltips(iPercent, 0);
//		alert(giOverallProgress);
	}
//	alert (percent+" : "+giOverallProgress);

	//	ON INITIAL LOAD, ANIMATE PROGRESS BAR
	showProgress(bInit);
}

//	UPDATE PROGRESS TOOLTIPS
function updateProgressTooltips (iPercent, iHow)
{
	var iLevelInProgress = giLevelInProgress;
	var sFirst = gsFirstName;
	if (isLoggedInAsSifu() && iHow == 1) 
	{
		iLevelInProgress = giMasterLevelInProgress;
		sFirst = gsMasterFirstName;
	}
	
	var sDesc = iPercent+"% of the way to Level "+iLevelInProgress;
	var sTip2 = "You are "+sDesc;
	var sTip = "Click to enter your Performance Tracker, "+sFirst+".";
	sTip = sTip+ "\n\n"+sTip2;
	if (iHow == 0)
	{
		setTooltip("logged_in", sTip);
		setTooltip("myOverallLevel",sTip2);
	}
	else if (iHow == 1)
		setTooltip("overallLevel",sTip2);
}

// GRAPH OF HOW FAR DONE, ANIMATE PROGRESS BAR
function showProgress (bInit)
{
	showActualProgress(bInit,"", giLevel, giLevelInProgress, giOverallProgress);
}

// GRAPH OF HOW FAR DONE, ANIMATE PROGRESS BAR
function showActualProgress (bInit, extra, iLevel, iLevelInProgress, iOverallProgress)
{
//	DON'T TRY TO PROGRES IF THERE IS NO PROGRESS BAR
	if (!document.getElementById("progressBar"+extra))
		return;
	
	var iTotalBar = document.getElementById("levelsImg"+extra).clientWidth;
	var iOneLevel = iTotalBar/10;
	var iProgressDone = (iLevelInProgress-1)*iOneLevel+((Math.min(1000,iOverallProgress)*iOneLevel)/1000);
	var iProgressShow = 0;
	if (extra=="")
	{
		giProgressDone = iProgressDone;
		giProgressShow = iProgressShow;
	}
	//	SIMPLER BAR (ONE SHOWS ONE LEVEL)
	else
	{
	//	DON'T SHOW MORE THAN 100% IN BAR
		iProgressDone = Math.min((iOverallProgress*iTotalBar)/1000, iTotalBar);
//		iProgressDone = (iOverallProgress*iTotalBar)/1000;
		if (isStatsPage())
		{
			giProgressDone = iProgressDone;
			giProgressShow = 0;
		}
	}
	
	//	COLORED PROGRESS BAR (ANIMATED OR STATIC)
	document.getElementById("progressBar"+extra).style.width = 0;
	
	if (bInit && bAnimateProgress && (isStatsPage()||extra==""))
	{
		var iDelay = 75;
		if (isStatsPage())
			iDelay = 35;
		giIntervalID = setInterval("animateProgress()", iDelay);
		if (isStatsPage())
			gsExtra = extra;
	}
	else
	{
		document.getElementById("progressBar"+extra).style.width = iProgressDone;
		if (document.getElementById("smallAvatar"))
			document.getElementById("smallAvatar").style.left = iProgressDone;
	}
		
	//	COLOR FOR LEVEL BAR
	if (document.getElementById("levelHeader"))
		document.getElementById("progressBar"+extra).style.background = document.getElementById("levelHeader").bgColor;
	else
		document.getElementById("progressBar"+extra).style.background = getLevelColor(iLevelInProgress);
		
	//	LAST LEVEL
	if (document.getElementById("lastLevel"+extra))
		document.getElementById("lastLevel"+extra).style.left = (iOneLevel*10)-6;
	
	//	LEVEL THEY ARE AT
	if (extra!="" || (iLevel > 0 && iLevel < 10))
	{
		var iShowLevel = iLevel;
		var iThis = iOneLevel*iLevel;
		if (isStatsPage())
			iThis = -2;
		else if (extra!="")
			iThis = -10;
		if (iLevel == 10)
			iShowLevel = 9;
		document.getElementById("thisLevel"+extra).style.left = iThis;
		setText("thisLevel"+extra,iShowLevel);
	}
	else
		document.getElementById("thisLevel"+extra).style.visibility='hidden';
	
	//	LEVEL THEY ARE WORKING TOWARD	
	if (extra!="" || (iLevelInProgress < 10))
	{
		var iThis =  iOneLevel*iLevelInProgress;
		if (isStatsPage())
		{
			iThis = iTotalBar-5;
			if (iLevel == 10)
				iThis -= 4;
		}
		else if (extra!="")
		{
			iThis = iTotalBar-10;
			if (iLevel == 10)
				iThis -= 4;
		}
		document.getElementById("nextLevel"+extra).style.left = iThis;
		setText("nextLevel"+extra,iLevelInProgress);
	}
	else
		document.getElementById("nextLevel"+extra).style.visibility='hidden';
}

//	GET COLOR FOR EACH LEVEL
function getLevelColor (iLevel)
{
	switch (iLevel)
	{
		default:
		case 0: return '#FFD98A';
		case 1: return '#FFD98A';
		case 2:	return '#FFD98A';
		case 3: return '#FF9122';
		case 4: return '#6699FF';
		case 5: return '#543399';
		case 6: return '#8B0000';
		case 7: return '#493C6A';
		case 8: return '#CA9800';
		case 9: return '#E8AE00';
		case 10: return '#FFCC33';
	}
}

//	ANIMATE PROGRESS BAR
function animateProgress ()
{
	giProgressShow += giProgressDone/60;
	if (giProgressShow >= giProgressDone)
	{
		clearInterval (giIntervalID);
		giProgressShow = giProgressDone;
	}
	document.getElementById("progressBar"+gsExtra).style.width = giProgressShow;
	if (document.getElementById("smallAvatar"))
		document.getElementById("smallAvatar").style.left = giProgressShow;
}

//	FUNCTION USEFUL WHEN WE CATCH ONCLICK
function doNothing()
{}

//	RETURN IMAGE CORRESPONDING TO PROGRESS PERCENT
function getPercentImage (iPercent)
{
	if (iPercent >= 100)
	{
		return sImageBase+"green.png";
	}
	else if (iPercent >= 85)
	{
		return sImageBase+"almost_green.png";
	}
	else if (iPercent >= 50)
	{
		return sImageBase+"amber.png";
	}
	else
	{
		return sImageBase+"red.png";
	}		
}

//	ADD TO PRACTICE COUNT FOR THIS SKILL
function addSkill(id)
{
	//	GET SKILL NAME
	var sSkill=getSkill(id);	
//	alert("addSkill #"+id+" ("+sSkill+")");
	if (iPracticedToday[id] < 2 && gbAllowRecordsChange)
		iPracticed[id]++;
	
	//	SHOW OVERALL PROGRESS
	describeOverall(false);
	
	//	UPDATE DISPLAY & DATABASE WITH PROGRESS
	updateSkill(id, 1);
}

//	REMOVE PRACTICE FOR THIS SKILL (TO CORRECT A MISTAKE)
function dropSkill(id)
{
//	alert("dropSkill "+id);
	var sSkill=getSkill(id);	

	if (iPracticed[id] > 0 && gbAllowRecordsChange)
	{
		iPracticed[id]--;
		
		//	SHOW OVERALL PROGRESS
		describeOverall(false);
	
		//	UPDATE DISPLAY & DATABASE WITH PROGRESS
		updateSkill(id, -1);
	}
}

//	GET XMLREQUEST (AJAX HANDLE)
function getRequest ()
{
	var xml_HTTP;
	if (window.XMLHttpRequest)
	{// code for IE7+, Firefox, Chrome, Opera, Safari
		xml_HTTP = new XMLHttpRequest();
	}
	else
	{// code for IE6, IE5
		xml_HTTP = new ActiveXObject("Microsoft.XMLHTTP");
	}
	// return the created object or display an error message
  if (!xml_HTTP)
    alert("Error creating the XMLHttpRequest object.");
  else 
    return xml_HTTP;
}
	
//	GET NUMBER FROM A STRING	
function getNumber (sStr)
{
	return parseInt(sStr,10);
}	

//	DETERMINE WHAT CLASS IS ON NEXT OR NOW
function determineThisClass ()
{ 	
	gsAttendanceStatus[0] = "";
	gsAttendanceStatus[1] = "";

	//alert("determineThisClass");
	xmlhttp2 = getRequest();
	
	var dateCheck = new Date();	
	var nowDate=dateCheck.format("yyyy/mm/dd");
	
	var sID="";
	if (isSkillPage())
		sID = gsUserID;
		
	var sReq = sURLBase+"class.php?plan=false&date="+nowDate+"&id="+sID+"&uniq="+Math.random();
//	alert (sReq);
	xmlhttp2.open("GET",sReq,true);
	xmlhttp2.onreadystatechange = receiveClassInfo;
	xmlhttp2.send(null);
}

//	 RECEIVE INFORMATION ABOUT THIS CLASS
function receiveClassInfo ()
{
	if (xmlhttp2.readyState==4 && xmlhttp2.status==200)
	{
		sResponse = xmlhttp2.responseText;	
		sResponse = trimSpaces(sResponse);
//		alert (sResponse);
		
		var theClass=sResponse.split(";");
	
		gsUpcomingClass[0] = theClass[0];
		gdateStart = new Date(getNumber(theClass[1])*1000);
		gdateNextFinish = new Date(getNumber(theClass[2])*1000);
		var ageInSeconds = Math.floor((gdateNextFinish.getTime() - gdateStart.getTime()) / 1000);
		giClassDurationMinutes = ageInSeconds/60;
		
		giNextClassID[0] = getNumber(theClass[3]);
		giNextClassIndex[0] = getNumber(theClass[4]);
		gsUpcomingClass[1] = theClass[5];
		gCurrentStart = new Date(getNumber(theClass[6])*1000);
		gCurrentEnd = new Date(getNumber(theClass[7])*1000);
		giNextClassID[1] = getNumber(theClass[8]);
		giNextClassIndex[1] = getNumber(theClass[9]);
		
		//	UPDATE ATTENDANCE PAGE ONCE PER MINUTE
		var iInterval = 2*1000;
		updateAttendance();
		clearInterval (giUpdateID);
		giUpdateID = setInterval("updateAttendance()", iInterval);
	
		//	FOR ATTENDANCE PAGE, SHOW DATA AND LOAD STUDENT DATA
		if (!isSkillPage() && !isLessonPlan())
		{
			//	SET DATE ON PAGE
			var showDate=gdateNow.format("dddd, mmmm dS, yyyy");
			setText("classDate",showDate);
			
			//	NOW THAT WE KNOW THE CLASS, LOAD STUDENT CLASS LIST
			reloadPage();	
		}
	}
}

//	DETERMINE CLASS LIST TO SHOW
function determineClassForPlan (iPrevIndex)
{ 	
	//alert("determineClassForPlan");
	xmlhttp8 = getRequest();

	var nowDate=gdateNow.format("yyyy/mm/dd");
	
	var sReq = sURLBase+"class.php?plan=true&date="+nowDate+"&prevIndex="+iPrevIndex+"&index="+giClassIndex+"&uniq="+Math.random();
//	alert (sReq);
	xmlhttp8.open("GET",sReq,true);
	xmlhttp8.onreadystatechange = receiveClassForPlan;
	xmlhttp8.send(null);
}

//	 RECEIVE INFORMATION ABOUT THIS CLASS
function receiveClassForPlan ()
{
	if (xmlhttp8.readyState==4 && xmlhttp8.status==200)
	{
		sResponse = xmlhttp8.responseText;	
		sResponse = trimSpaces(sResponse);
//		alert (sResponse);
		
		var theClass=sResponse.split(";");
	
		setText("className",theClass[0]);
		giClassIndex = getNumber(theClass[1]);

		setText("classTime",theClass[2]);
		
		gdateNow = new Date(getNumber(theClass[3])*1000);
		gdateEndClass = new Date(getNumber(theClass[6])*1000);
		
		//	SET DATE ON PAGE
		var showDate=gdateNow.format("dddd, mmmm dS, yyyy");
		setText("classDate",showDate);
		
		//	NOW THAT WE KNOW THE CLASS, LOAD STUDENT CLASS LIST
		reloadPage();	
	}
}

//	SHOW NEXT CLASS IN VIEW
function nextClass ()
{
	if (!isLoggedInAsSifu() && !isLoggedInAsSeimu())
		return;
		
	dateIncrement = 1;
	if (isLessonPlan())
	{
		var iPrevIndex = giClassIndex;
		giClassIndex++;
		if (giClassIndex > 8)
			giClassIndex = 0;
		determineClassForPlan(iPrevIndex);
	}	
	//	ADVANCE TO NEXT DAY
	else
	{
		giClassIndex=-1;
		date2 = gdateNow.getDate()+dateIncrement;
		gdateNow.setDate(date2);
		determineThisClass();
	}
}

//	SHOW PREVIOUS CLASS
function previousClass ()
{
	if (!isLoggedInAsSifu() && !isLoggedInAsSeimu())
		return;
		
	dateIncrement = -1;
	
	if (isLessonPlan())
	{
	//	alert("current class is #"+giClassIndex);
		var iPrevIndex = giClassIndex;
		giClassIndex--;
		if (giClassIndex < 0)
			giClassIndex = 8;		
//	alert("change to class #"+giClassIndex);
		determineClassForPlan(iPrevIndex);
	}	
	else
	{
		giClassIndex=-1;
		//	PREVIOUS DAY
		date2 = gdateNow.getDate()+dateIncrement;
		gdateNow.setDate(date2);
		determineThisClass();
	}
}

function deleteAllCookies ()
{
	var cookies = document.cookie.split(";");
	for (var i = 0; i < cookies.length; i++)
	{
		var sCookie = trimSpaces(cookies[i]);
		Delete_Cookie(sCookie.split("=")[0],'/', "");
	}
}
  
//	DO PERSONAL LOGOUT
function logout ()
{
	gsFirstName="";
	
	deleteAllCookies();
//	setCookie("firstName",gsFirstName);
//	Delete_Cookie ("firstName", '/', "");

//	alert (document.cookie);
	
	//	IF ON A LEVEL PAGE, LOAD ACADEMY PAGE NOW
	if (pageRequiresLogin())
		gotoAcademyPage();
	else
		window.location.reload();
}

//	LOAD ACADEMY PAGE
function gotoAcademyPage ()
{
	var sPage = sURLBase+"academy.htm";
	window.location.href = sPage;
}

//	GET INNER HTML FOR ELEMENT
function getHTML (sElement)
{
	if (document.getElementById(sElement))
		return document.getElementById(sElement).innerHTML;
}

//	SET INNER HTML FOR ELEMENT
function setHTML (sElement, sHtml)
{
	if (document.getElementById(sElement))
		document.getElementById(sElement).innerHTML=sHtml;
}
	
//	DO PERSONAL LOGIN 
function doLogin ()
{
	sUser = document.getElementById("username").value;
	sPassword = document.getElementById("password").value;
	return actualDoLogin(sUser,sPassword, true);
}

//	DO PERSONAL LOGIN 
function actualDoLogin (sUser,sPassword, bGoUserPage)
{
	//	IF AUTOMATED LOGIN, STAY ON SAME PAGE, OTHERWISE GO TO USER'S PAGE
	gbGoUserPageOnLogin = bGoUserPage;
	
	xmlhttp3 = getRequest();
	xmlhttp3.open("GET",sURLBase+"login.php?username="+sUser+"&password="+sPassword+"&uniq="+Math.random(),true);
	xmlhttp3.onreadystatechange = receiveLogin;
	xmlhttp3.send(null);
	return false;
}

//	 RECEIVE LOGIN INFORMATION
function receiveLogin ()
{
	if (xmlhttp3.readyState==4 && xmlhttp3.status==200)
	{
		var sResponse = xmlhttp3.responseText;	
//		alert ("login1:("+sResponse+")");
		sResponse = trimSpaces(sResponse);

//		alert ("login2:("+sResponse+")");
		//	LOGIN FAILED?
		if (sResponse.search("failed") != -1)
		{
			if (document.getElementById("loginFailed"))
				document.getElementById("loginFailed").style.visibility='visible';
		}
		//	LOGIN SUCCEEDED?
		else
		{	
			var theUser=sResponse.split(",");
			gsFirstName = theUser[0];
			gsLastName = theUser[1];
			gsAvatarURL = theUser[2];
			giLevel = getNumber(theUser[3]);
			giLevelInProgress = giLevel+1;
			if (giLevelInProgress > 10)
				giLevelInProgress = 10;
			gsUserID = theUser[4];
			giOverallProgress = getNumber(theUser[5]);
//			alert(giOverallProgress);
			var bNegativeProgress = checkForProgressGuess();
		
			//	LOGGED IN AS SIFU?		
			if (gsFirstName == "Sifu Bill")
			{
				gsMasterFirstName = gsFirstName;
				gsMasterLastName = gsLastName;
				gsMasterAvatarURL = gsAvatarURL;
				giMasterLevel = giLevel;
				gsMasterUserID = gsUserID;
				giMasterOverallProgress = giOverallProgress;	
				
				setCookie("masterfirstName",gsMasterFirstName);
				setCookie("masterlastName",gsMasterLastName);
				setCookie("masterAvatarURL",gsMasterAvatarURL);
				setCookie("masterlevel",giMasterLevel);
				setCookie("masteruserID",gsMasterUserID);
				setCookie("masterprogress",giMasterOverallProgress);		
			}	
		//	alert("user ("+gsFirstName+") validated, take user to their personal page for their level");
			
			//	LOGIN SUCCEEDED?
			setCookie("firstName",gsFirstName);
			setCookie("lastName",gsLastName);
			setCookie("AvatarURL",gsAvatarURL);
			setCookie("level",giLevel);
			setCookie("userID",gsUserID);
			if (!bNegativeProgress)
				setCookie("progress",giOverallProgress);
			
			if (isStatsPage())
			{
				createPersonalStats();
//				describeStudent();
			}
			//	SHOULD WE GO TO USER'S PAGE UPON LOGIN?
			else if (gbGoUserPageOnLogin)
				goto_userPage();
	//		showLoggedIn();
		}
	}
}

//	GET A PARAMETER FROM A QUERY STRING
function getQueryParam (sAll, sFind)
{
	var sAllValues = sAll.split('&');
	var sPair = '';
	var sName = '';
	var sValue = '';
	var b_cookie_found = false; // set boolean t/f default f

	for ( i = 0; i < sAllValues.length; i++ )
	{
		// now we'll split apart each name=value pair
		sPair = sAllValues[i].split('=');


		// and trim left/right whitespace while we're at it
		sName = sPair[0].replace(/^\s+|\s+$/g, '');

		// if the extracted name matches passed check_name
		if (sName == sFind)
		{
			// we need to handle case where cookie has no value but exists (no = sign, that is):
			if (sPair.length > 1)
			{
				sValue = unescape( sPair[1].replace(/^\s+|\s+$/g, '') );
			}
			// note that in cases where cookie is initialized but no value, null is returned
			return sValue;
			break;
		}
		sPair = null;
		sName = '';
	}
	return "";
}

// this fixes an issue with the old method, ambiguous values
// with this test document.cookie.indexOf( name + "=" );
function Get_Cookie( check_name ) 
{
	// first we'll split this cookie up into name/value pairs
	// note: document.cookie only returns name=value, not the other components
	var a_all_cookies = document.cookie.split( ';' );
	var a_temp_cookie = '';
	var cookie_name = '';
	var cookie_value = '';
	var b_cookie_found = false; // set boolean t/f default f

	for ( i = 0; i < a_all_cookies.length; i++ )
	{
		// now we'll split apart each name=value pair
		a_temp_cookie = a_all_cookies[i].split( '=' );


		// and trim left/right whitespace while we're at it
		cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');

		// if the extracted name matches passed check_name
		if ( cookie_name == check_name )
		{
			b_cookie_found = true;
			// we need to handle case where cookie has no value but exists (no = sign, that is):
			if ( a_temp_cookie.length > 1 )
			{
				cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
			}
			// note that in cases where cookie is initialized but no value, null is returned
			return cookie_value;
			break;
		}
		a_temp_cookie = null;
		cookie_name = '';
	}
	if ( !b_cookie_found )
	{
		return null;
	}
}

function Set_Cookie( name, value, expires, path, domain, secure )
{
// set time, it's in milliseconds
var today = new Date();
today.setTime( today.getTime() );

/*
if the expires variable is set, make the correct
expires time, the current script below will set
it for x number of days, to make it for hours,
delete * 24, for minutes, delete * 60 * 24
*/
if ( expires )
{
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );

document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
( ( path ) ? ";path=" + path : "" ) +
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
}

// this deletes the cookie when called
function Delete_Cookie( name, path, domain ) 
{
if ( Get_Cookie( name ) ) 
	document.cookie = name + "=" + ( ( path ) ? ";path=" + path : "") +
	( ( domain ) ? ";domain=" + domain : "" ) +
	";expires=Thu, 01-Jan-1970 00:00:01 GMT";
}

//	DEFAULT EXPIRY IN 2 YEARS
function setCookie (c_name,value)
{
	//	COOKIES EXPIRE IN 2 YEARS
	var exdays = 2*365;
	Set_Cookie(c_name, value, exdays, '/', '', '');
}

function setCookie1(c_name,value,exdays)
{
var exdate=new Date();
exdate.setDate(exdate.getDate() + exdays);

var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
document.cookie=c_name + "=" + c_value;
}

function getCookie(c_name)
{
	return Get_Cookie(c_name);
}

function getCookie1(c_name)
{
var i,x,y,ARRcookies=document.cookie.split(";");
for (i=0;i<ARRcookies.length;i++)
{
  x=ARRcookies[i].substr(0,ARRcookies[i].indexOf("="));
  y=ARRcookies[i].substr(ARRcookies[i].indexOf("=")+1);
  x=x.replace(/^\s+|\s+$/g,"");
  if (x==c_name)
    {
    return unescape(y);
    }
  }
}

//	SHOW LOGGED IN DIV
function showLoggedIn() 
{	
	//alert("logged in as "+gsFirstName);
	//	HIDE LOGIN UI STUFF
	if (!document.getElementById("loginBtn"))
		return;
		
	document.getElementById("loginBtn").style.visibility='hidden';
	document.getElementById("login").style.visibility='hidden';
	document.getElementById("loginFailed").style.visibility='hidden';

	//	CUSTOMIZE DIV THAT SHOWS USER IS LOGGED IN
	var sAvatar = gsAvatarURL;
	var sFirst = gsFirstName;
	var sLast = gsLastName;
	var iOverall = giOverallProgress;
	var iLevel = giLevel;
	
	if (isLoggedInAsSifu())
	{
		sAvatar = gsMasterAvatarURL;
		sFirst = gsMasterFirstName;
		sLast = gsMasterLastName;
		iOverall = giMasterOverallProgress;	
		iLevel = giMasterLevel;
	}
	
	document.getElementById("imgAvatar").src=sURLBase+sAvatar;
	setText("firstName",sFirst);
	if (sFirst.length > 7)
	document.getElementById("firstName").style.fontSize = '16px';
	setText("theLastName",sLast);

	// alert(giOverallProgress);
	document.getElementById("overallLevel").src=getPercentImage(iOverall/10);
	var iPercent = iOverall/10;
	updateProgressTooltips(iPercent, 1);
		
	setText("theLevel",iLevel);
	
	document.getElementById("show_logged_in").style.position='absolute';
	document.getElementById("show_logged_in").style.width='150px';
	document.getElementById("show_logged_in").style.top = 0;
	document.getElementById("show_logged_in").style.right = 1;
	document.getElementById("show_logged_in").style.marginRight = 1;
	document.getElementById("show_logged_in").style.visibility='visible';
	document.getElementById("logged_in").style.visibility='visible';
}

var cX = 0; var cY = 0; var rX = 0; var rY = 0;
function UpdateCursorPosition(e){ cX = e.pageX; cY = e.pageY;}
function UpdateCursorPositionDocAll(e){ cX = event.clientX; cY = event.clientY;}
if(document.all) { document.onmousemove = UpdateCursorPositionDocAll; }
else { document.onmousemove = UpdateCursorPosition; }

function AssignPosition(d,x,y) 
{
	if(self.pageYOffset) 
	{
		rX = self.pageXOffset;
		rY = self.pageYOffset;
	}
	else if(document.documentElement && document.documentElement.scrollTop) 
	{
		rX = document.documentElement.scrollLeft;
		rY = document.documentElement.scrollTop;
	}
	else if(document.body) {
		rX = document.body.scrollLeft;
		rY = document.body.scrollTop;
		}
	if(document.all) 
	{
		cX += rX; 
		cY += rY;
	}
//	d.style.left = (cX+10-(iWidth/2)) + "px";
//	d.style.top = (cY+10+20) + "px";
	
	d.style.left = (x+10) + "px";
	d.style.top = (y+10+20) + "px";
}

function hideLevelPopup() 
{
	giShowLevel = 0;
	var d = "levelPopup";
	if(d.length < 1) { return; }
	document.getElementById(d).style.display = "none";
}

function showLevelPopup(ev) 
{
	if (navigator.appName == 'Microsoft Internet Explorer')
		return;
		
	if (ev == null) { ev = window.event }

	//	GET POSITION, SIZE OF BAR	
	var iTotalBar = document.getElementById("levelsImg").clientWidth;
	var iBarX = document.getElementById("levelsImg").x;
	var iBarY = document.getElementById("levelsImg").y;
//	var iBarX = document.getElementById("levelsImg").offsetLeft;
//	var iBarY = document.getElementById("levelsImg").offsetTop;

	var iOneLevel = iTotalBar/10;

	var mX = ev.clientX-iBarX;
	var mY = ev.clientY-iBarY;	
	var iTheLevel = Math.floor(mX/iOneLevel);
	
	//	LEVEL POPUP ALREADY SHOWING?
	if (giShowLevel == iTheLevel+1)
		return;
	
	giShowLevel = iTheLevel+1;
	var iX = iBarX+(iTheLevel*iOneLevel)+(iOneLevel/2)-giLevelWidth/2-20;
	
	var sText = "Level "+giShowLevel;
	setText("levelHdr",sText);
	sText = describeLevel(giShowLevel);
	document.getElementById("levelInfo").innerHTML = sText;
//	setText("levelInfo",sText);
	
	var dd = document.getElementById("levelPopup");
	dd.style.width = giLevelWidth;
	AssignPosition(dd, iX, iBarY);
	if(dd.style.display == "none") { dd.style.display = "block"; }
	else { dd.style.display = "none"; }
}

function describeLevel(iLevel)
{
	var sText;
	switch (iLevel)
	{
		case 1: sText="Theme: A Little Idea, The Basics<br>Basic stepping, striking, arm moves and defenses."; break;
		case 2: sText="Theme: Footwork<br>More stepping, striking, basic arm moves and defenses."; break;
		case 3: sText="Theme: Simultaneous Block & Punch<br>Complete Sil Lum Tao, perfecting the basics, get ready for advanced kung fu."; break;
		case 4: sText="Theme: Trapping & Get to the Outside<br>Advanced stepping, expand defense techniques"; break;
		case 5: sText="Theme: Apply Chi Sao & Bridge The Gap<br>Learn to use the wooden dummy, intermediate chi sao & defense combinations."; break;
		case 6: sText="Theme: Advanced Chi Sao & Mobility Defending<br>More Chi sao, round out defense skills."; break;
		case 7: sText="Theme: Goal Setting, Commitment & Focus<br>Advanced combinations and weapons. Start to look beyond technique."; break;
		case 8: sText="Theme: Commitment & Stay Focused<br>Learn Bil Jee strikes, advanced grappling, look toward mastery."; break;
		case 9: sText="Theme: Random Sides<br>Complete your technical skills, slow down time, get prepared for the final level."; break;
		case 10: sText="Theme: Fully Random<br>Master every technique, every form, every weapon and combination. Master yourself in any situation."; break;
	}
	return sText;
}

function showLevelPopup2() 
{
	var d = "levelPopup";
	if(d.length < 1) { return; }
	var dd = document.getElementById(d);
	AssignPosition(dd);
	dd.style.display = "block";
}
function ReverseContentDisplay(d) 
{
	if(d.length < 1) { return; }
	var dd = document.getElementById(d);
	AssignPosition(dd);
	if(dd.style.display == "none") { dd.style.display = "block"; }
	else { dd.style.display = "none"; }
}

//	HANDLE CLICK ON CHECKBOX ON COMMAND PAGE
function checkboxHandler (e)
{
	if (!e)
	e = window.event;

	if (e.cancelBubble)
		e.cancelBubble = true;
	else
		e.stopPropagation();
	
	//	ON LESSON PLAN PAGE, ADJUST PLAN ON ANY CHECKBOX CHANGE
	if (isLessonPlan())
		createLessonPlan();
}

//	GET STRING DESCRIBING ELAPSED TIME
function elapsedTime (dateNow, dateReference, bEnding)
{
  var ageInSeconds = Math.floor((dateNow.getTime() - dateReference.getTime()) / 1000);
  var sEnding = " ago";
  if (ageInSeconds < 0) 
  {	
		ageInSeconds =-ageInSeconds;
		sEnding = " from now";
  }
  if (!bEnding)
		sEnding = "";
		    
  var s = function(n) { return n == 1 ? '' : 's' };
 
  if (ageInSeconds < 60) 
  {
      var n = ageInSeconds;
      return n + ' second' + s(n) + sEnding;
  }
  //	MINUTES
  if (ageInSeconds < 60 * 60) 
  {
      var n = Math.floor(ageInSeconds/60);
      return n + ' minute' + s(n) + sEnding;
  }
  //	HOURS
  if (ageInSeconds < 60 * 60 * 24) 
  {
      var n = Math.floor(ageInSeconds/60/60*10);
      n = n/10;
      return n + ' hour' + s(n) + sEnding;
  }
  if (ageInSeconds < 60 * 60 * 24 * 7) {
      var n = Math.floor(ageInSeconds/60/60/24);
      return n + ' day' + s(n) + sEnding;
  }
  if (ageInSeconds < 60 * 60 * 24 * 31) {
      var n = Math.floor(ageInSeconds/60/60/24/7);
      return n + ' week' + s(n) + sEnding;
  }
  if (ageInSeconds < 60 * 60 * 24 * 365) {
      var n = Math.floor(ageInSeconds/60/60/24/31);
      return n + ' month' + s(n) + sEnding;
  }
  var n = Math.floor(ageInSeconds/60/60/24/365);
  return n + ' year' + s(n) + sEnding;
}

//	UPDATE LIVE INFORMATION ON ATTENDANCE PAGE
function updateAttendance ()
{	
	//	NO DATA YET?
	if (gsUpcomingClass[0] == "" || !document.getElementById("classInfo") && !document.getElementById("classInfo_0"))
		return;
		
	var sStatus = "??";
	var sStatus = describeClassTime(gsUpcomingClass[0], gdateStart, gdateNextFinish, 0);
	var sStatus2 = describeClassTime(gsUpcomingClass[1], gCurrentStart, gCurrentEnd, 1);

	changeAttendanceStatus(sStatus,0);	
	changeAttendanceStatus(sStatus2,1);		
}

//	DETERMINE HOW LONG TILL CLASS START/END
function  describeClassTime (sClass, dateStart, dateNextFinish, iNum)
{
	var dateRightNow = new Date();
//		
//	//	CLASS STARTS IN FUTURE?
	var sDescribe = "???";
	var sRet = "!??";
	divid = "attend"+iNum;
	clockid = "clock_"+iNum;
	
	if (sClass == "")
	{
		if (document.getElementById(divid))
			document.getElementById(divid).style.display = 'none';
		if (document.getElementById(clockid))
			document.getElementById(clockid).style.display = 'none';	
	}
			
	if (sClass == "")	
		return sClass;
	
	//	CLASS STARTS IN FUTURE?		
	if (dateStart.getTime() > dateRightNow.getTime())
	{
		sDescribe = elapsedTime(dateRightNow, dateStart, true);
		sRet = sClass+" Class starts "+sDescribe;
    if (document.getElementById(divid))
			document.getElementById(divid).style.display = 'inline';
	}
	//	CLASS IS OVER?
	else if (dateRightNow.getTime() > dateNextFinish.getTime())
	{
		sDescribe = elapsedTime(dateRightNow, dateNextFinish, true);
		sRet = sClass+" Class finished "+sDescribe;
		if (document.getElementById(divid))
			document.getElementById(divid).style.display = 'none';
	}
	//	IN MIDDLE OF CLASS
	else
	{	
		//	IS IT 1/2 HR AFTER START OF CLASS? 
		//	THEN ITS TIME TO EMAIL THE LESSON PLAN TO ATTENDING STUDENTS
		var ageInSeconds = Math.floor((dateRightNow.getTime() - dateStart.getTime()) / 1000);
		var iAgeInMinutes = ageInSeconds/60;
		
		//	AT 28 MINS INTO CLASS, TURN ON SWITCH ALLOWING LESSON PLAN TO BE SENT TO STUDENTS
		if (isActualAttendancePage())
		{
			if (iAgeInMinutes >= 28 && iAgeInMinutes < 30 && gsLessonToSend!="send" && gsLessonToSend != sClass)
				gsLessonToSend = "send";
				
			//	IF 28 MIN SWITCH WAS SET, THEN SEND LESSON PLAN AT 30 MINS INTO CLASS
			if (iAgeInMinutes >= 30 && iAgeInMinutes <= 31 && gsLessonToSend == "send")
				emailPlanToStudents(sClass, giNextClassIndex[iNum]);
		}
		
		sDescribe = elapsedTime(dateRightNow, dateNextFinish, true);
		sRet = sClass+" is ON now! Class finishes "+sDescribe;
		if (document.getElementById(divid))
			document.getElementById(divid).style.display = 'none';
	}
	
	//	DON'T SHOW LINKS TO JOIN CLASS IF NOT A SKILL PAGE
	if (!isSkillPage() && document.getElementById(divid))
		document.getElementById(divid).style.display = 'none';	
		
	// TEMP REMOVE ATTEND LINKS
//	if (document.getElementById(divid))
//		document.getElementById(divid).style.display = 'none';
				
	return sRet;
}

//	ONLY SHOW STATUS IF CHANGED
function changeAttendanceStatus (sString, iNum)
{
	if (sString == gsAttendanceStatus[iNum])
 		return;	
	gsAttendanceStatus[iNum] = sString;
	var divid = "classInfo_"+iNum;
	setText(divid,gsAttendanceStatus[iNum]);	
}


//	SEND sType TYPE OF EMAIL TO sID USER
function sendEmailToUser (sID, sType)
{
	var sURL = "emailLogin.php";
	var sRequest = "id="+sID+"&emailType="+sType;
	
	//	SEND CUSTOM SUBJECT & MESSAGE TEXT?
	if (sType == "customNewsletter")
		sRequest+="&subject="+gsSubject+"&message="+gsMessage;
	
	doPost(sURL, sRequest, receiveEmailCallback);
	if (sType == 'birthday')
		alert("Birthday email sent to student "+sID);
}

function stripslashes (str) 
{
    return (str + '').replace(/\\(.?)/g, function (s, n1) {
        switch (n1) {
        case '\\':
            return '\\';
        case '0':
            return '\u0000';
        case '':
            return '';
        default:
            return n1;
        }
    });
}

//	DO AJAX POST & CALL A CALLBACK METHOD WITH RETURN DATA
function doPost (sURL, sRequest, sCallback)
{
	xmlhttp7 = getRequest();
	if (!xmlhttp7)
		return;
	xmlhttp7.open("POST",sURL,true);
	
	//Send the proper header information along with the request
	xmlhttp7.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
	xmlhttp7.setRequestHeader("Content-length", sRequest.length);
	xmlhttp7.setRequestHeader("Connection", "close");

	xmlhttp7.onreadystatechange = sCallback;
	xmlhttp7.send(sRequest);

}

//	AJAX RECEIVE CALLBACK ON SENDING EMAIL
function receiveEmailCallback ()	
{
	if (xmlhttp7.readyState==4 && xmlhttp7.status==200)
	{
		//	PROCESS RESPONSE		
		var sResponse = xmlhttp7.responseText;	
		sResponse = trimSpaces(sResponse);	
		
		//	PREVIEW EMAIL CONTENT?
		if (sResponse.search("SUBJECT:") != -1)
		{
			var index = sResponse.search("MESSAGE:");
			if (index != -1)
			{
//				alert (sResponse);
				
				var sData = sResponse.split('<body topmargin=\"10\" leftmargin=\"10\">');
				var sContent = sData[1].split('</body>')[0];
			
//				alert (sContent);
				showEmailPreview(sContent);
			}
		}	
	}
}

//	INFORM SERVER THAT STUDENT WILL BE ATTENDING OR NOT ATTENDING FORTHCOMING CLASS
function studentWillAttend (iUserID, iClassID, bAttend)
{
	//	ATTENDING OR NOT?
	var sAttending="";
	var iActualClassID = iClassID;
	gbClassChanged = bAttend;
	
	if (bAttend)
	{	
		sAttending = "";
		iClassID+=700;
	}
	else
	{
		iClassID+=600;
		sAttending = "NOT ";
	}
		
	//	SEND CHANGE TO USER'S ATTENDANCE, REQUEST UPDATED STUDENT DATA
	xmlhttp = getRequest();	
		
	var nowDate;
	nowDate=gdateNow.format("yyyy/mm/dd");

	var showDate;
	showDate=gdateNow.format("dddd, mmmm dS, yyyy h:MM TT");
		
	//	MESSAGE TO USER
//	if (bAttend)
//	{
//		 sMsg = "Now we know "+iUserID+" will be attending class "+iActualClassID+" on "+showDate+".";
//	}
//	else
//	{
//		 sMsg = "Now we know "+iUserID+" will not be attending class "+iActualClassID+" on "+showDate+".";
//		 sMsg+= "\n\nThat will help us optimize the lesson plan for others who will be attending."
//	}
//	alert(sMsg);
			
	xmlhttp.open("GET",sURLBase+"attendance.php?userID="+iUserID+"&addAttendance=true&date="+nowDate+"&classIndex=-2&classID="+iClassID+"&uniq="+Math.random(),true);
	xmlhttp.onreadystatechange = receiveStudentAdvanceChanged;
	xmlhttp.send(null);
}

//	INFORM SERVER THAT STUDENT WILL BE ATTENDING OR NOT ATTENDING FORTHCOMING CLASS
function willAttend (iClass, bAttend)
{
	//	ATTENDING OR NOT?
	var sAttending="";
	var iClassID=giNextClassID[iClass];
	giClassChanged = iClass;
	gbClassChanged = bAttend;
	
	if (bAttend)
	{	
		sAttending = "";
		iClassID+=200;
	}
	else
	{
		iClassID+=100;
		sAttending = "NOT ";
	}
		
	//	SEND CHANGE TO USER'S ATTENDANCE, REQUEST UPDATED STUDENT DATA
	xmlhttp = getRequest();	
		
	var nowDate;
	if (!iClass)
		nowDate=gdateStart.format("yyyy/mm/dd");
	else
		nowDate=gCurrentStart.format("yyyy/mm/dd");
	var showDate;
	if (!iClass)
		showDate=gdateStart.format("dddd, mmmm dS, yyyy h:MM TT");
	else
		showDate=gCurrentStart.format("dddd, mmmm dS, yyyy h:MM TT");
		
	//	MESSAGE TO USER
	if (bAttend)
	{
		 sMsg = "Thanks for letting us know you will be attending "+gsUpcomingClass[giClassChanged]+" on "+showDate+".";
		 sMsg+= "\n\nWe will include the skills you most need to work on in the lesson plan."
	}
	else
	{
		 sMsg = "Thanks for letting us know you will not be attending "+gsUpcomingClass[giClassChanged]+" on "+showDate+".";
		 sMsg+= "\n\nThat will help us optimize the lesson plan for others who will be attending."
	}
	alert(sMsg);
			
	xmlhttp.open("GET",sURLBase+"attendance.php?userID="+gsUserID+"&addAttendance=true&date="+nowDate+"&classIndex=-2&classID="+iClassID+"&uniq="+Math.random(),true);
	xmlhttp.onreadystatechange = receiveStudentAdvanceChanged;
	xmlhttp.send(null);
}

//	GET AJAX RESPONSE IF READY
function isAJAXReady (aXMLhttp)
{
	if (aXMLhttp.readyState==4 && aXMLhttp.status==200)	
	{
		sResponse = aXMLhttp.responseText;
		sResponse = trimSpaces(sResponse);
		return sResponse;
	}
	else
		return "";
}	
		
//	STUDENT INDICATED IF THEY ARE ATTENDING UPCOMING CLASS
function receiveStudentAdvanceChanged ()
{
	sResponse = isAJAXReady(xmlhttp);
	if (sResponse == "")
		return;
	
	//	NO ACTION REQUIRED IF LESSON PLAN
	if (isLessonPlan())
		return;

//			alert(sResponse);		
	var userInfo=sResponse.split(",");
	var userID = userInfo[0];
	var bAdd = userInfo[1];
	var iNum = giClassChanged;

	//	REMOVE HYPERLINK
	var divid = "attend"+iNum;
	if (document.getElementById(divid))
	{
		if (gbClassChanged)
		{
			document.getElementById(divid).innerHTML = 'will attend';	
			document.getElementById(divid).style.color = 'Blue';				
//			alert ("tell server that user "+gsUserID+" is "+sAttending+"attending class "+giNextClassID[iClass]+" on "+nowDate);				
		}
		else 
		{
			document.getElementById(divid).innerHTML = 'will not attend';	
			document.getElementById(divid).style.color = 'Red';	
		}
	}
}

//	SET QUOTE & SHOW IT
function setQuote (sQuote, sAuthor)
{
	setText("quote", sQuote);
	setText("quoteAuthor", sAuthor);
	
	document.getElementById("wholeQuote").style.visibility='visible';
}

//	EMAIL PLAN TO ALL ATTENDING STUDENTS
function emailPlanToStudents (sClass, iClassIndex)
{
	gsLessonToSend = sClass;

//	alert("email all attending students the lesson plan for class"+sClass+" today");
	
	xmlhttp = getRequest();		
	xmlhttp.open("GET",sURLBase+"dailyPlan.php?task=sendStudentOnePlan&classIndex="+iClassIndex+"&uniq="+Math.random(),true);
	xmlhttp.onreadystatechange = emailPlanCallback;
	xmlhttp.send(null);
}

//	FEEDBACK ON SENDING TODAY'S LESSON PLAN TO STUDENTS WHO ATTENDED
function emailPlanCallback ()
{
	if (xmlhttp.readyState==4 && xmlhttp.status==200)
	{
		sResponse = xmlhttp.responseText;
		sResponse = trimSpaces(sResponse);
//			alert(sResponse);				
	}
}
