// Bob Hanson hansonr@stolaf.edu 3:38 PM 4/27/2009

// conflict for courses at MWF 905-1000 and TTh 8-9:20 but not lab
// [MWF9]MWF 905-1000 [TThlab]TTh 927-928  [TTh9]TTh 0935-1100 
// look for TThlab "availability" but not the other two



var theYear = 2009
var theTerm = 1
var theDept = ""
var theSearch = ""

$(function () {
	// document ready function via jQuery
	div("getWhat").value = theSearch
	loadSemesterData()
})



var docsearch = document.location.search.substring(1)
if (docsearch.indexOf("term=") >= 0) {
	var t = parseInt(docsearch.split("term=")[1])
	if(!isNaN(t)) {
		theTerm = t % 10
		theYear = (t - theTerm) / 10
	} 
}
if (docsearch.indexOf("dept=") >= 0) {
	theDept = docsearch.split("dept=")[1].split("&")[0].toLowerCase()
}
if (docsearch.indexOf("search=") >= 0) {
	theSearch = docsearch.split("search=")[1].split("&")[0]
}

var thisyearterm = "" + theYear + theTerm

var classlabBase = (document.location.href.indexOf("https:") == 0 ? "https:" : "http:") + "//www.stolaf.edu/classlab/" //20083/

sisBase = "https://www.stolaf.edu/sis/"

var isLocal = (document.location.href.indexOf("file:") == 0)

var Terms = ["","Semester 1","Interim","Semester 2"]

var isPostRegistrationPage = false

var thisdept = 0
var nextdept = 0
var theseCourses = []
var Students = []
var thisIndex = 0
var results = ""
var nStudents = 0
var nStudentsFiltered = 0
var header = ""
var theResults = ""
var degreeAudit = true
var courseInfo = false
var courseConflicts = false
var emailOnly = false
var majorInfo = false
var headerOnly = false
var showGrades = false
var htmlOnly = false
var commaSeparated = false
var infoType = "tool-stuinfo.cfm"
var searchyearterm = "20091"
var thisId = ""
var notIds = ""
var thisClass = ""
var recordContains = ""
var DTtimeSets = []
var saveCourseId = ""
var studentList = ""

var includeTypeRequested = ""
var includeFilterRequested = ""
var includeTypeRegistered = ""
var includeFilterRegistered = ""

var CourseDataById = {}

function yearTermBox() {
	var s = '<select class="sis-formfont" id="searchyearterm">'
	for (var i = theYear + 2; --i >=theYear-1;)
	  for (var j = 1; j <=3; j++) {
		s+='<option value="' + i + "" + j + '"'  + (i==theYear && j == theTerm ? ' selected':'') + '>' 
			+ i + "-" + (i + 1) + ', ' + Terms[j] + '</option>'
	  }
	s+='</select>'
	return s
}

function resetFilter(which) {
	div('conflictTimes').value=''
	div('resultDiv').innerHTML=''
	switch (which) {
	case 1:
		Students = []
		nStudents = 0
		nStudentsFiltered = -1
		div('registrationContains').value='same'
		div('studentList').innerHTML=''
		setTimeout("loadIdList()",100)
		break
	case 2:
		if (nStudents == 0 || div("studentRegistrations").value == "")return
		findStudents()
		break
	}
	
}

function setOptions() {
	lineContains = ""
	courseConflicts = false
	if (div("dataType")) {
		isPostRegistrationPage = false
		var S = getSelected("dataType").value.split("?")
		dataSource = S[0]
		dataType = S[1]
		thisId = div("studentId").value
		notIds = div("notStudentIds").value
		thisClass = div("classOf").value
		recordContains = div("recordContains").value
		emailOnly = div("email").checked
		degreeAudit = div("degreeAudit").checked
		courseInfo = !emailOnly && !degreeAudit || div("courseInfo").checked
		studentList = div("stulist").value
		if (degreeAudit) {
			infoType = "st-degreeaudit.cfm"
			showGrades = div("showGrades").checked
			majorInfo = div("majorInfo").checked
			headerOnly = (majorInfo || div("headerOnly").checked)
			lineContains = (!headerOnly ? div("lineContains").value : "")
		}

		var d = getSelected("searchyearterm")
		searchyearterm = d.value
		thisyearterm = d.text	
		courseConflicts = courseInfo && div("courseConflicts").checked
	} else {
		isPostRegistrationPage = true
		courseInfo = true
	}
	if (courseInfo){
		lineContains += ",sis-coursename"
		infoType = "st-courses.cfm"
	}

	conflictTimes = div("conflictTimes").value.replace(/\n/g," ")

	htmlOnly = div("htmlSource").checked
	commaSeparated = (majorInfo || lineContains || courseConflicts) && div("commaSeparated").checked
}

function loadIdList(frominput) {
	div("resultDiv").value = ""
	setOptions()
	if (frominput) {
		if(studentList)loadStudentIds(studentList)
		return
	}
	if (!isLocal)div("studentRegistrations").value = ""
	var ids = setStudentRequests()
	if(!ids) {
		alert("No student IDs to process. Did you copy the Student request data into the yellow textarea?")
		return false
	}
	loadStudentIds(ids)
	return true
}

function showIdList(which) {
	var idList = ""
	switch (which) {
	case 1:
		if (!loadIdList())return
		checkStudents(true)
		idList += nStudents + "\tREQUESTED\t" + includeTypeRequested + " " + includeFilterRequested + "\n\n"
		break
	case 2:
		if (nStudents == 0 || div("studentRegistrations").value == "")return
		findStudents()
		idList += nStudentsFiltered + "\tREGISTERED\t" + includeTypeRegistered + " " + includeFilterRegistered + "\n\n"
		break
	}
	idList += "\t\t" + ("" + new Date()).split("GMT")[0] + "\n\n"
	popupWindow("<pre>" + idList + getCheckedStudentList() + "</pre>")
}

function getRegistrationData(postProcess) {
	if (!postProcess)postProcess=""
	saveCourseId = "studentRegistrations"
	if (Students.length == 0)loadIdList()
	checkStudents(true)
	loadStudentInfo(0,postProcess)
}

function findStudents() {
	if (Students.length == 0 || div("studentRegistrations").value == "") {
		getRegistrationData("checkStudentRegistrations()")
		return
	}
	setOptions()
	checkStudentRegistrations()
}

var StudentInfoFromId={}
function setStudentRequests() {
	//NAME	STNO	CLASS	YR	TRM	RNK	CRS1	CRS2	CRS3	CRS4	CRS5	CRS6
	var data = div("studentRequests").value
	var includeType = includeTypeRequested = getSelected("requestIncludes").text
	var includes = (includeType == "includes" ? 1 : includeType == "does not include" ? -1 : 0)
	includeFilterRequested = div("requestContains").value
	var filter = fixFilter(includeFilterRequested.split(","))
	var sep = (data.indexOf("\t") >= 0 ? "\t" : ",")
	var S = data.split("\n")
	var stulist = ""
	StudentInfoFromId = {}
	var requests = []
	var idlast = ""
	var nthis = 0
	for (var i = 1; i < S.length; i++) {
		var line = S[i]
		var s = line.split(sep)
		if (!s[1])continue
		var name = s[0]
		var id = fixId(s[1])
		var classyear = s[2]
		thisyearterm = searchyearterm = s[3]+s[4]
		var nrank = s[5]
		if (id != idlast) {
			requests = []
			idlast = id
			nthis = 0
		}		
		requests.push(line.split("\t"))
		if (stulist.indexOf(id) < 0 && includes && passesFilter(line, includes, filter)) {
			stulist += id + " "
			if (nthis == 0)nthis = nrank
			StudentInfoFromId[id] = [name, classyear, requests, nthis]
		}
	}
	loadStudentIds(stulist)
	return stulist
}

function checkStudentRegistrations() {
	var includeType = includeTypeRegistered = getSelected("registrationIncludes").text
	var includes = (includeType == "includes" ? 1 : includeType == "does not include" ? -1 : 0)
	if (includes == 0)return
	var data = getTabTableMatrix(div("studentRegistrations").value, ",")
	var courses = getColumn(data, 3)
	var labs = getColumn(data, 4)
	var ids = getColumn(data, 1)
	var times = getColumn(data, 10)
	var filter = getRegistrationFilter();
	mapStudents()
	for (var i = 0; i < Students.length; i++) {
		Students[i].n = 0
		Students[i].courses = []
		Students[i].courseList = ""
	}
	for (var i = 0; i < courses.length; i++) {
		if (!courses[i])continue
		var sid = ids[i]
		if (!Map[sid])continue
		var student = Students[Map[sid][0]]
		student.courses.push(data[i])
		if (courses[i].indexOf("Total Credits:") >= 0) {
			student.credits = setCredits(data[i][4]);
		} else if (courses[i].indexOf("Course #") < 0) {
			student.courseList += courses[i] + " "
		}
		if (passesFilter(courses[i],true,filter))student.n++
	}
	var n = 0
	for (var i = 0; i < Students.length; i++) {
		var check = (includes == 1 && Students[i].n > 1 || includes == -1 && Students[i].n == 0)
		div("ckstudent" + i).checked = Students[i].checked = check
		if (check) n++
	}
	nStudentsFiltered = n
	div("nStudentsFiltered").innerHTML = n + " students"
}

function setCredits(s) {
	var c = parseFloat(s.split("&")[0])
	return (isNaN(c) ? 0 : c)
}

function getRegistrationFilter() {
	var s = div("registrationContains").value
	if (s.indexOf("same")>=0)s = div("requestContains").value
	includeFilterRegistered = s
	return fixFilter(s.split(","))
}

function fixFilter(F) {
	for (var i = 0; i < F.length; i++) {
		F[i] = F[i].replace(/^\s+/g,"").replace(/\s+$/g,"") 
	}
	return F
}

function getTimes() {
	calculateConflictTimes()
}

function calculateConflictTimes() {
	div("conflictTimes").value = ""
	var data = getTabTableMatrix(div("studentRegistrations").value, ",")
	if (data.length == 0) {
		alert("The course-time information is in the registration data. Get the registration data first.")
		return false
	}
	courses = getColumn(data, 3)
	var labs = getColumn(data, 4)
	var times = getColumn(data, 10)
	var filter = getRegistrationFilter();
	var C = {}
	D = []
	for (var i = 0; i < courses.length; i++) {
		if (!courses[i])continue
		var lcourse = (labs[i] == "L" ? 1 : 0) + courses[i]
		if (C[lcourse] || !passesFilter(courses[i],true,filter)) continue
		C[lcourse] = times[i]
		D[D.length] = [courses[i],lcourse, courses[i].split(" ")[1] + (labs[i] == "L" ? "L" : "") ]
	}
	D = D.sort(labsort)
	var s = ""
	var slast = "xxxxx"
	for (var i = 0; i < D.length; i++) {
		var name = D[i][2]
		if (name.substring(0,3) != slast) {
			slast = name.substring(0,3)
			if (s) s+= ";"
		}
		s += "[" + name + "] " + C[D[i][1]] + "\n"
	}
	div("conflictTimes").value = s
	return true
}

function checkConflicts() {
	if (div("conflictTimes").value == "" && !calculateConflictTimes()) return
	findStudents()
	var info = ""
	getCourseTimes()
	for (var i = 0; i < Students.length; i++) {
		if (div("ckstudent"+i).checked)
			info += getConflictInfo(i)
	}
	courseConflicts = true
	setResults(info)
}

function getConflictInfo(index) {
	var courseTimes = Students[index].courseTimes
	var DTcourses = getDayTimeSetFromColumns(courseTimes.join(",").replace(/\ ,/g,",").replace(/,\ /g,",").split(","))
	var tdinfo = ""
	var name0 = ""
	for (var i = 0; i < DTtimeSets.length; i++) {
		var DTtimes = DTtimeSets[i]
		for (var j = 0; j < DTtimes.length; j++) {
			var DT = DTtimes[j]
			var isconflict = DT.isconflict = false
			for (var k = 0; k < DTcourses.length; k++) {
				if (isConflict(DT,DTcourses[k])) {
					DT.isconflict = isconflict = true
					break 
				}
			}
			if (DT.name.indexOf("_") >= 0){
				var pt = tdinfo.indexOf(name0)
				if (isconflict && pt >= 0) {
					tdinfo = tdinfo.substring(0,pt) + tdinfo.substring(pt + name0.length)
				}
			} else {
				name0 = DT.name
				tdinfo += "<td width=60 valign=top>" + (isconflict ? "&nbsp;" : DT.name) + "</td>"
			}
		}
	}
	return "<tr><td valign=top>" + Students[index].id 
		+ "</td><td valign=top>" + Students[index].classyear
		+ "</td><td valign=top>" + roundoff(Students[index].credits,2)
		+ (Students[index].requests ? "</td><td valign=top><a href=javascript:showStudentRequests(" + index + ")>#" + Students[index].firstRankedCourse + "</a>" : "")
		+ "</td><td width=200 valign=top><a href=javascript:showStudentData(" + index + ") title='"+ Students[index].courseList+"'>" + Students[index].name + "</a>"
		+ "</td>" + tdinfo + "</tr>"
}

function showStudentRequests(index) {
	var swhat = tabulateTabs(Students[index].requests)
	popupWindow(swhat,"menubar,scrollbars,resizable,alwaysRaised,width=900,height=600,left=50,top=50")
}

function showStudentData(index) {
	var swhat = CourseDataById[Students[index].id] 
	if (!swhat)swhat = tabulateTabs(Students[index].courses)
	swhat = "<tiny>" + swhat + "</tiny>"
	popupWindow(swhat,"menubar,scrollbars,resizable,alwaysRaised,width=800,height=600,left=50,top=50")
}


function labsort(a,b) {
  return a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0
}

function filterPrefix(name, filter) {
	for (var i = 0; i < filter.length; i++) {
		if (name.indexOf(filter[i])==0)return name.substring(filter[i].length)
	}
	return name
}

Map = {}
function mapStudents() {
	Map = {}
	for (var i = 0; i < Students.length; i++)Map[Students[i].id] = [i] 
}

function getCourseTimes() {
	var data = getTabTableMatrix(div("studentRegistrations").value, ",")
	var ids = getColumn(data, 1)
	var courses = getColumn(data, 3)
	var times = getColumn(data, 10)
	mapStudents()
	for (var i = 0; i < Students.length; i++) {
		Students[i].courseTimes = []
	}
	for (var i = 0; i < courses.length; i++) {
		if (!courses[i])continue
		var sid = ids[i]
		if (!Map[sid])continue
		Students[Map[sid][0]].courseTimes.push(times[i])
	}
}


function getHeader(withConflictTimes) {
	setOptions()
	var theHeader = ""
	if (!withConflictTimes) return thisyearterm
	DTtimeSets = getDayTimeSetsWithLabels(conflictTimes)
	theHeader = "<h3>Course sections without time conflict for " + thisyearterm + " " + ("" + (new Date())).split(" GMT")[0] + "</h3><table><tr>"
	for (var i = 0; i < DTtimeSets.length; i++) {
		theHeader += "<td valign=top><table>"
		for (var j = 0; j < DTtimeSets[i].length; j++)
			theHeader += "<tr><td>[" + DTtimeSets[i][j].name + "]</td><td>" + DTtimeSets[i][j].daytimes + "</td></tr>"
		theHeader += "</table></td>"
	}
	theHeader += "</table>"
	return theHeader
}

function passesFilter(s, includes, filter) {
	var n = 0
	for (var j = 0; j < filter.length; j++)
		if (s.indexOf(filter[j]) >= 0)n++
	return !(includes == 1 && n == 0 || includes == -1 && n > 0)
}

function fixId(stid) {
	stid = stid.replace(/ /g,"")
	if (stid.length < 5)return ""
	stid = "0" + stid
	return stid.substring(stid.length, stid.length-6) 
}

function checkStudents(tf) {
	for(var i = 0; i < nStudents; i++) {
		div("ckstudent" + i).checked = Students[i].checked = tf
	}
}

function getCheckedStudentList() {
	var idList = ""
	for (var i = 0; i < Students.length; i++)
		if (Students[i].checked)
			idList += Students[i].classyear 
			+ "\t"  + roundoff(Students[i].credits,2) 
			+ "\t"  + Students[i].id 
			+ "\t" + Students[i].name + "\n"
	return idList
}

function loadStudentList() {
	div("errors").innerHTML = "getting student list ... "
	Students = []
	setOptions()
	var url = sisBase + dataSource
	var data = (dataType ? dataType : "")
	loadXmlData(url, data, processStudentList, false)
}

function extractStudentList(info) {
	var records = getTagsByClassName(info, "tr", "sis-line*")
	var n = 0
	for (var i = 0; i < records.length; i++) {
		var r = records[i]
		if (classOf && r.indexOf(">" + thisClass + "<") < 0) continue
		if (recordContains && r.indexOf(recordContains) < 0) continue
		var name = getTagByClassName(r, "td", "sis-name")
		var id = getTagByClassName(r, "td", "sis-idnum")
		var classyear = getTagByClassName(r, "td", "sis-classyear")
		id = id.substring(0,6)
		if (thisId && id.indexOf(thisId) != 0) continue
		if (notIds.indexOf(id) >= 0) continue
		Students[n] = {}
		Students[n].name = name
		Students[n].id = id
		Students[n].classyear = classyear
		Students[n].credits = 0
		nStudents = ++n
	}
	setStudentList()
	if (htmlOnly)div("resultDiv").innerHTML = "<pre> " + info.replace(/\</g,"&lt;") + "</pre>"
}

function loadStudentIds(ids) {
	Students = []
	ids = ids.replace(/\D/g," ")
	var S = ids.split(" ")
	var n = 0
	for (var i = 0; i < S.length; i++){
		var stid = fixId(S[i])
		if (!stid)continue
		var Student = {}
		Student.info = StudentInfoFromId[stid]
		if (Student.info){
			Student.name = Student.info[0]
			Student.classyear = Student.info[1]
			Student.requests = Student.info[2]
			Student.firstRankedCourse = Student.info[3]
		} else {
			Student.name = "[" + stid + "]"
			Student.classyear = ""
		}
		Student.credits = 0
		Student.id = stid
		Students[n++] = Student
	}
	nStudents = n
	nStudentsFiltered = -1
	setStudentList()
}

function setStudentList() {
	var s = nStudents + " students <label><input type='checkbox' id='ckstudents' onclick='checkStudents(checked)'> check/uncheck all</label> "
	if (isPostRegistrationPage) {
		div("nStudents").innerHTML = nStudents + " students"
	} else {
		s += "<a href=javascript:getData()>get data</a>"
	}
	s += "<pre><br>================================================="
	for (var i = 0; i < Students.length; i++) {
	        s += "\n<label><input type='checkbox' id='ckstudent" + i + "' > " 
		  + Students[i].classyear + " " 
		  + Students[i].id + " " 
		  + "<span id=sname" + Students[i].id + ">" + Students[i].name + "</span></label>"
	}
	s += "</pre>"
	div("studentList").innerHTML = s
}

function getData() {
	loadStudentInfo(0)
}

var loadStudentPostProcess
var loadStudentYearTerm

function loadStudentInfo(i, postProcess) {
	thisIndex = i
	if (thisIndex == 0) {
		loadStudentYearTerm = thisyearterm.substring(0,4) + "-"
		loadStudentPostProcess=(postProcess ? postProcess : "")
		div("resultDiv").innerHTML = ""
		theResults = ""
		if (saveCourseId)div(saveCourseId).value = ""
		req = null
	}

	if (!div("ckstudent" + i).checked) {
		setTimeout('nextStudent()',10);
		return
	}
	setOptions()
	div("errors").innerHTML = "getting student info for " + Students[i].name + "... "
	var info = CourseDataById[Students[i].id]
	if (info) {
		extractStudentInfo(info)
		return
	}
	var url = sisBase + infoType
	var data = (emailOnly ? "idnum=" + Students[i].id : "stnum=" + Students[i].id + "&searchyearterm=" + searchyearterm)
	loadXmlData(url, data, processStudent, false)
}

function extractStudentInfo(info) {
	var name = Students[thisIndex].name
	var id = Students[thisIndex].id
	CourseDataById[id] = info
	if (name.indexOf("[")==0) {
		var d = div("sname" + id)
		d.innerHTML = name = Students[thisIndex].name = info.split(" for ")[1].split("<")[0]
	}
	setOptions()
	if (headerOnly && !majorInfo || saveCourseId)commaSeparated = false
	if (!showGrades)info = info.replace(/align=left/g,"style='display:none'")
	if(emailOnly && !htmlOnly){
		info = "<table><tr><td>" + getTagByClassName(info, "a") + "</td></tr></table>"
	} else if (lineContains) {
		var S = lineContains.split(",")
		var sinfo = "<td>" + Students[thisIndex].classyear + "</td><td>" 
			+ Students[thisIndex].id + "</td>"
		        + "<td>" + Students[thisIndex].name + "</td>"
		var s = ""
		info = info.substring(info.indexOf("Course Summary") + 1)
		var lines = getTagsByClassName(info, "tr", "sis-line*", "sis-tbl*")
		for (var i = 0; i < lines.length; i++) {
			var isOK = false
			for (var j = 0; j < S.length; j++)
			  if (lines[i].indexOf(S[j]) >= 0) {
				isOK = true
				break
			  }
			if (!isOK)continue
			s += "<tr>" + sinfo + lines[i] + "</tr>"
		}
		info = "<hr><table>" + s + "</table>"
	} else if (headerOnly) {
		info = info.substring(0, info.indexOf("General Graduation Requirements"))
		info += "</td></table></body></html>"
		if (majorInfo) {
			info = "<hr>" + getTableContaining(info, "th>Majors<")
			if (!htmlOnly)info = tabulate(info, Students[thisIndex])
		}
	}
	info = fixLinks(info)
	if (saveCourseId || courseConflicts)
		Students[thisIndex].courseTimes = getTableColumn(info,10) 
	if (courseConflicts) {
		var lines = getTagsByClassName(info, "td", "sis-credits")
		if (lines.length)Students[thisIndex].credits = setCredits(lines[lines.length - 1]);
		info = getConflictInfo(thisIndex)
	}
	if (commaSeparated) {
		info += "<tr><td></td></tr>"
	}
	if (htmlOnly)
		info = "<pre>" + info.replace(/\</g,"&lt;") + "\n---------------------------------------------------------</pre>"
	theResults += info
	div("errors").innerHTML = "&nbsp;"
	header = ""
	nextStudent()
}

function nextStudent() {
	if (++thisIndex < Students.length) {
		loadStudentInfo(thisIndex)
		return
	}

	// done

	setResults(theResults)

	if (loadStudentPostProcess)setTimeout(loadStudentPostProcess,10)
}

function setResults(s) {
	if (courseConflicts) s = "<table border=1 cellspacing=0>" + s + "</table>"
	s = getHeader(courseConflicts) + s
	if (saveCourseId){
		div(saveCourseId).value = getTabSeparated(s)
		saveCourseId = ""
	}
	if (commaSeparated) {
		s = "<pre>" + getCommaSeparated(s) + "</pre>"
	}
	div("resultDiv").innerHTML = s
}

//////// drop down boxes created dynamically using AJAX


///////// --- old -----

function loadInfoTable() {
	div("errors").innerHTML = ""
	var url = sisBase + "tool-aclasslab.cfm"
	loadXmlData(url, "", processInfoTable, false)
}

function extractInfoTable(info) {
	var s = getTagByClassName(info, "form",0,true)
	if (s.indexOf("Login") >= 0) {
		s = "<a href=javascript:loadInfoTable()>Load term/department information</a>"
		+ ' <a target="_blank" href="https://www.stolaf.edu/sis/">log in</a>'
		div("infolink").innerHTML = s
		return
	}
	s = s.replace(/ name\=/g," id=")
		.replace(/submit\"/,"button\" onclick=loadClassLabData(0)")
	var script = getTagByClassName(s, "script", 0, true)

	// SIS bug: improper TermMsgs = new Array() causes Firefox3 to create an array of length 20094, even though using quotes in TermMsgs["nnnnn"]
	script = script.replace(/var /,"").replace(/new Array\(\)/,"{}")
	eval(script)
	div("infotable").innerHTML = s
	div("searchcomment").style.display = "block"
	div("searchinput").style.display = "block"
	div("searchbutton").value = "Get Course Data"
}

function showtermmsg() {
	var msg = TermMsgs[getSelected("searchyearterm").value]
	if (msg)div('termmsg').innerHTML = msg
}


var Pwr2 = []; Pwr2[0] = 1
{
   for (var i = 1; i < 10; i++)Pwr2[i] = Pwr2[i-1]<<1
}

mysched=""

function getInfo(what) {
	if (!what) what = div("getWhat").value
	what = what.replace(/ or /ig," or ").replace(/ and /ig," and ")
	var isAll = (what == "*")
	if (isAll) what=""
	theSearch = what
	div("getWhat").value = what
	var isor = (what.indexOf(" or ")>0)
	var openonly = div("openonly").checked
	var W = what.split(isor ? " or " : " and ")
	for (var i = 0; i < W.length; i++)W[i] = W[i].replace(/\_/g," ")
	var xp = Pwr2[W.length] - 1 // binary 111111
	var Data = []
	var s
	for (var i = 0; i < W.length; i++) {
		var isLC = (W[i] == W[i].toLowerCase())
		W[i] = [W[i], isLC]
	}
	for (var i = 0; i < ClassLabCourses.length;i++) {
		var n = 0
		var pwr = 0
		var course = ClassLabCourses[i]
		if (openonly && course.coursestatus == "C") continue
		for (j in course) {
			if (isAll || (pwr = docheck(W,pwr,("" + course[j]))) == xp
				  || isor && pwr != 0) {
				Data[Data.length] = course
				break
			}
		}
	}
	document.frm.title.value=theDept + " " + thisyearterm + " " + what 
	document.frm.mytimes.value = getSchedule(Data)
	showCourses(Data, div("asgraphic").checked)
}

function docheck(W,pwr,s) {
	var lcs = s.toLowerCase()
	for (var i = 0; i < W.length; i++)
		if ((W[i][1] ? lcs : s).indexOf(W[i][0]) >= 0) {
			pwr |= Pwr2[i]
		}
	return pwr
}

function getSchedule(C) {
	var noC = !C
	if (noC)C = ClassLabCourses
	C0 = C
	var S = ""
	for (var i = 0; i < C.length; i++) {
		var c = C[i]
		for (var j = 0; j < c.meetingtimes.length; j++) if (c.meetingtimes[j]){
			s=fixtime(c.meetingtimes[j])+" " 
			+ c.deptname+c.coursenumber+c.coursesection+("LD".indexOf(c.coursesubtype) >= 0 ? c.coursesubtype : "") + "\n"
			if (S.indexOf(s) < 0) S += s
		}
	}
	return S
}

function fixtime(s) {
	var S = s.split("-")
	return (S[0].substring(0,S[0].length-2) + ":" + S[0].substring(S[0].length-2) 
		+ "- " + S[1].substring(0,2) + ":" +S[1].substring(2)).replace(/ 0/g," ").replace(/\- /g,"-")
}

function doshowsched() {
	div("mytimes") = mysched
}

function checkEnter(e) {
	var keycode = (window.event ? window.event.keyCode : e ? e.which : 0);
	if (keycode == 13) {
		setTimeout("getInfo()",100)
	}
}

function gridDisplay() {
	getInfo()
	dodisplay(true)
}

function showHTML() {
	getInfo()
	doshowhtml(true)
}

function showJSON() {
	popupWindow("<pre>"+JSON.stringify(theseCourses,null," ")+"</pre>")
}

function showTabData() {
	popupWindow("<pre>"+getTabSeparated(div("resultDiv").innerHTML)+"</pre>")
}

function getDayTimeTable(Times) {
	var sout = "<table border=0 cellpadding=0 cellspacing=0>"
	for (var i = 0; i < Times.length; i++) {
		var DT = getDayTimes(Times[i])
		if (!DT.bsDays)continue
		sout += "<tr height=10>"
		+ getBars(1,DT, mycolorof(DT.bsDays,1),10) 
		+ getBars(0,DT, mycolorof(DT.bsDays,0),10)
		+ "</tr>"
	}
	return sout + "</table>"
}

function getBars(isMWF, DT, color, divisor) {
	if (!divisor)divisor = 4
	var time1 = DT.Times[0] - 600
	var time2 = DT.Times[1] - 600
	time1 = (Math.floor(time1 / 100) + (time1 % 100)/60)*100
	time2 = (Math.floor(time2 / 100) + (time2 % 100)/60)*100
	if (isMWF && !DT.isMWF || !isMWF && !DT.isTTh) time2 = time1
	var w1 = Math.floor(time1 / divisor)
	var w2 = Math.floor((time2 - time1) / divisor)
	var w3 = Math.floor((2200 - 600 - time2) / divisor)
	return "<td width='" + w1 + "'></td>"
		+(w2 == 0 ? "" : "<td title='"+DT.daytimes + "' style='background-color:" + color + "' width=" + w2 + "></td>")
//+"<td>" + w1 + " " + w2 + " " + w3 + " " +(time2-time1) + " " + time1 + " " + time2 + "</td>"
		+"<td width='" + w3 + "'></td>"
}


//////////// input data methods /////////

function div(id) {
	return document.getElementById(id)
}

function getSelected(s) {
	return div(s)[div(s).selectedIndex]
}

function fixLinks(info) {
	info = info.replace(/value="st/g,'value="' + sisBase + 'st')
	info = info.replace(/value="addr/g,'value="' + sisBase + 'addr')
	info = info.replace(/\<form/g, "<form target='_blank'")
	info = info.split("</html>")[0] + "</html>"
	return info
}

function getCommaSeparated(table) {
	var lines = getTableMatrix(table)
	for (var i = 0; i < lines.length; i++) {
		var line = lines[i]
		for (var j = 0; j < line.length; j++)line[j]= '"' + line[j].replace(/\"/g,"'").replace(/\&nbsp\;/g,"") + '"'
		lines[i] = lines[i].join(",")
	}
	return lines.join("\n").replace(/\<table\>/g,"")
}

function getTabSeparated(table) {
	var lines = getTableMatrix(table, ",")
	for (var i = 0; i < lines.length; i++)lines[i] = lines[i].join("\t").replace(/\&nbsp\;/g," ")
	return lines.join("\n")
}

function getTableColumn(table, col) {
	var lines = getTableMatrix(table, ",")
	return getColumn(lines, col)
}

function getColumn(data, col) {
	var Cols = []
	for (var i = 0; i < data.length; i++)
		Cols[i] = data[i][col]
	return Cols
}

function getTableMatrix(table, linesep) {
	if (!linesep)linesep=" "
	var lines = getTagsByClassName(table, "tr")
	for (var i = 0; i < lines.length; i++)
		lines[i] = getTagsByClassName(lines[i], "td")
	for (var i = 0; i < lines.length; i++) {
		for (var j = lines[i].length; --j >= 0;)
			lines[i][j] = cleanData(lines[i][j], linesep)
	}	
	return lines
}

function getTabTableMatrix(table) {
	var lines = table.split('\n')
	for (var i = 0; i < lines.length; i++)lines[i] = lines[i].split('\t')
	return lines
}

function getTagByClassName(data, tag, tagclass, asis) {
	var what = "<" + tag + (tagclass ? " class=\"" +tagclass + "\"" : "")
	var ret = data.split(what)[1]
	if (!ret)return ""
	var closer = "</" + tag + ">"
	ret = ret.substring(ret.indexOf(">") + 1).split(closer)[0]
	return (asis ? ret : cleanData(ret))
}

function getTagsByClassName(data, tag, tagclass, tagclass2) {
	var mayExtend = (tagclass && tagclass.indexOf("*") >= 0)
	if (mayExtend)tagclass = tagclass.split("*")[0]
	var mayExtend2 = (tagclass2 && tagclass2.indexOf("*") >= 0)
	if (mayExtend2)tagclass2 = tagclass2.split("*")[0]
	var S = data.split("<" + tag)
	var class1 = (tagclass ? " class=\"" +tagclass + (mayExtend ? "" : "\"") : "")
	var class2 = (tagclass2 ? " class=\"" +tagclass2 + (mayExtend2 ? "" : "\"") : "")
	var closer = "</" + tag + ">"
	var ret = []
	for (var i = 1; i < S.length; i++) {
		if (!class1 && !class2 
			|| class1 && S[i].indexOf(class1) >= 0 
			|| class2 && S[i].indexOf(class2) >= 0)
 			ret[ret.length] = S[i].substring(S[i].indexOf(">") + 1).split(closer)[0]
	}
	return ret
}

function cleanData(s,linesep) {
	if (!linesep)linesep=" "
	var i
	if (s.indexOf("<span")>=0)s = getTagByClassName(s, "span")
	s = s.replace(/\<\/a\>/g, "")
	while ((i = s.indexOf("<a")) >= 0)
		s = s.substring(0, i) + s.substring(s.indexOf(">", i) + 1)
	s = s.replace(/[\n|\r|\t]/g," ").replace(/\<br\>/g, linesep)
	s = s.replace(/\&nbsp\;/g,"")
	while (s.indexOf("        ")>=0)s = s.replace(/        /g," ")
	while (s.indexOf("    ")>=0)s = s.replace(/    /g," ")
	while (s.indexOf("  ")>=0)s = s.replace(/  /g," ")
	return s.replace(/^\s/,"").replace(/\s$/,"")
}

//////////// output data methods /////////

function tabulate(info, student) {
	info = info.replace(/th\>/g,"td>")
	var lines = getTagsByClassName(info, "tr", "sis*")
	var data = []
	var n = 0;
	var maxcol = 0;
	for (var i = 0; i < lines.length; i++) {
		data[n] = getTagsByClassName(lines[i],"td")
		maxcol = Math.max(maxcol, data[n].length)
		n++
	}
	var s = "<table>" 
	var sinfo = "<tr><td>" + student.classyear + "</td><td>" + student.id + "</td><td>" + student.name + "</td>"
	for (var i = 0; i < maxcol; i++)
		for (var j = 1; j < data.length; j++) {
			if (data[j][i]) s+=sinfo + "<td>" + data[0][i] + "</td><td>" + data[j][i] + "</td></tr>"
		}
	return s.replace(/\t/g,",") + "</table>"
}

function tabulateTabs(data) {
	// [tabbeddata,tabbeddata,tabbeddata]
	var s = "<table>"
	for (var i = 0; i < data.length; i++) {
		s += "<tr>"
		for (var j = 0; j < data[i].length; j++)s+= "<td>" + data[i][j] + "</td>"
		s += "</tr>"
	}
	s += "</table>"
	return s		
}

function getTableContaining(info, what) {
	var S = info.split("table>")
	for (var i = 0; i < S.length; i++)
		if (S[i].indexOf(what)>=0)
			return "<hr><br><table>"+S[i]+"table>"
	return ""
}

/////////////////////////////////////////////// AJAX //////////////////////////////////////////////////
//
//
//
//

function showErrors(text) {
	var e = div("errors");
	if (e)e.innerHTML = (text ? '<pre>'+text+'</pre>' : "")
}

function processInfoTable(info) {
	div("errors").innerHTML = ""
	extractInfoTable(info)
}

function processSemesterPage(info) {
	div("errors").innerHTML = ""
	extractSemesterPage(info)
}

function processDepartmentPage(info) {
	div("errors").innerHTML = ""
	extractDepartmentPage(info)
}

function processClassLabPage(info) {
	div("errors").innerHTML = ""
	extractClassLabPage(info)
}



function processStudentList(info) {
	div("errors").innerHTML = ""
	extractStudentList(info)
}

function processStudent(info) {
	if (req.responseText.indexOf("Sorry,") >= 0) {
		CourseDataById[Students[thisIndex].id] = ""
		alert("You need to log into the SIS system again.")
		req = null
		return
	} else if (courseInfo && req.responseText.indexOf(loadStudentYearTerm) < 0) {
		alert(CourseDataById[Students[thisIndex].id] = "There is no data for " + thisyearterm + " for " + Students[thisIndex].name+". It is possible that this student has a hold on registration.")
	}
	extractStudentInfo(info)
}

function processClassLabXml(xml) {
	//traverse(xml.documentElement);
	if (xml == null) {
		errors += req.responseText + "\n"
		return
	}
	extractClassLabInfo(xml)
}

var req
var Req = {} // local additions
var xmlProcessor = null
var isFF = (window.XMLHttpRequest ? true : false)
var errors = ""

function loadXmlData(url, data, processor, asXML) {
	xmlProcessor = processor
	try {
		req = (isFF ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"));
		Req.asXML = (asXML ? true : false)
		req.onreadystatechange = processStateChange;
		req.open("POST", url + (data ? "?" + data : ""), true);
		req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
		req.send(data);
	} catch (e) {
		alert(e);
	}
}

function processStateChange() {
	if (req.readyState != 4)
		return
	if (req.status != 200) {
		alert(req.statusText);
		return
	}
	var parser = 0
	if (!Req.asXML) {
		xmlProcessor(req.responseText)
		return
	}
	if (isFF) {
		try {
			parser = new DOMParser();
		} catch (e) {
			isFF = false
		}
	}
	if (isFF && parser) {
		try {
			// Firefox3 has some sort of bug that disallows req.responseXML
			// the problem is that some tags get truncated
			// which tag data gets truncated is not generally predictable
			// this from http://www.w3schools.com/Dom/dom_parser.asp
			xmlProcessor(parser.parseFromString(req.responseText,"text/xml"))
		} catch (e) {
			xmlProcessor(null)
		}
	} else {
		xmlProcessor(req.responseXML)
	}
}

///////////////////////////////////////////////// misc methods /////////////////////////////////////////////

woptions="menubar,scrollbars,resizable,alwaysRaised,width=450,height=600,left=50,top=50"

function popupWindow(swhat, options) {
	var s="<html>"+swhat+"</html>"
 	var sm=""+Math.random()
 	sm=sm.substring(3,10)
 	var newwin=open('','SIS_'+sm, options ? options : woptions)
 	newwin.document.write(s)
 	newwin.document.close()
}

//math,string utilities
function roundoff(x,ndec)
{
 //round x to ndec decimal places (+) fixed; (-) floating
 if(x==0)return 0
 if(ndec==0)return Math.round(x)
 var neg=(x<0?"-":"")
 var xs=Math.abs(x)+""
 var i=(xs.indexOf("E") & xs.indexOf("e"))
 if(ndec<0 && i<0)
 {
  var xs=roundoff(Math.abs(x)*1e-100,-ndec)
  var i=(xs.indexOf("E") & xs.indexOf("e"))
  var e=(eval(xs.substring(i+1,xs.length))+100)
  return neg+xs.substring(0,i)+(e!=0?"E"+e:"")
 }
 if (i>0)
 {
  var s=roundoff(xs.substring(0,i),Math.abs(ndec)-1)+"E"+xs.substring(i+1,xs.length)
  return neg+s 
 }
 i=xs.indexOf(".")
 if (i<0) 
 {
  xs=xs+"."
  i=xs.indexOf(".")
 }
 xs=xs+"000000000"
 var s="."+xs.substring(i+1+ndec,xs.length)
 xs=xs.substring(0,i)+xs.substring(i+1,i+1+ndec)
 var add1=(xs.charAt(0)=="0")
 if(add1)xs="1"+xs
 xs=eval(xs)+Math.round(eval(s))+""
 if(add1)xs=xs.substring(1,xs.length)
 xs=xs.substring(0,xs.length-ndec)+"."+xs.substring(xs.length-ndec,xs.length)
 if(xs.substring(0,1)==".")xs="0"+xs
 return neg+xs
}

///////////// new       


function loadSemesterData() {
	div("errors").innerHTML = ""
	var url = classlabBase
	loadXmlData(url, "", processSemesterPage, false)
}


Semesters = []

function setYearTerm() {
	var d = getSelected("searchyearterm")
	var yyyyt = d.value
	thisyearterm = d.text
	theYear = yyyyt.substring(0,4)
	theTerm = yyyyt.charAt(4)
	searchyearterm = yyyyt
	return yyyyt
}

var yearSelected = false

function extractSemesterPage(info) {
	var lines = info.split("<a href=\"20")
	Semesters = []
	yearSelected = false
	for (var i = 1; i < lines.length; i++) {
		var yyyyt = "20" + lines[i].substring(0,3)
		var name = lines[i].split(">")[1].split("<")[0]
		Semesters.push([yyyyt, name])
	}
	var s = '<select class="sis-formfont" id="searchyearterm" onchange=loadDepartmentData()>'
	for (var i = 0; i < Semesters.length; i++) {
		if (Semesters[i][0] == thisyearterm)yearSelected = true
		s+='<option value="' + Semesters[i][0] + '"'  + (Semesters[i][0] == thisyearterm ? ' selected':'') + '>' 
			+ Semesters[i][1] + '</option>'
	}
	s +='</select>'
	div("infotable1").innerHTML = s
	div("infogo").style.display="block"
	loadDepartmentData()
}


function loadDepartmentData() {
	Depts = [[]] // no "0" department
	ClassLabCourses = []
	div("errors").innerHTML = ""
	setYearTerm()
	var url = classlabBase + searchyearterm
	loadXmlData(url, "", processDepartmentPage, false)
}


Depts = [[]] // no "0" department
var deptSelected = false

function extractDepartmentPage(info) {
	deptSelected = false	
	var lines = info.split("<h2")[1].split("</ul>")[0].split("<a href=\"")
	for (var i = 1; i < lines.length; i++) {
		var code = lines[i].split('"')[0]
		var name = lines[i].split(">")[1].split("<")[0]
		if (code.indexOf("html") < 3)break
		Depts.push([code, name])
	}
	var s = '<select class="sis-formfont" id="searchdepartment"><option value="0" style="background-color:yellow">All Departments</a>'
	for (var i = 1; i < Depts.length; i++) {
		if(theDept && Depts[i][1].toLowerCase() == theDept) deptSelected = true
		
		s+='<option value="' + i + '"' + (theDept && Depts[i][1].toLowerCase() == theDept ? " selected" : "") + '>' + Depts[i][1] + '</option>'
	}
	s+='</select>'
	div("infotable2").innerHTML = s
	if (yearSelected && deptSelected) loadClassLab(0)
}

thisdept = -1
nextdept = 0

function loadClassLab(idept) {
	div("errors").innerHTML = ""
	var isAll = false
	theDept = ""
	if (idept == 0) {
		// "go"
		ClassLabCourses = []
		div("resultDiv").innerHTML = ""
		idept = thisdept = parseInt(getSelected("searchdepartment").value)
	} else if (idept < 0) {
		isAll = true
		idept = -idept
	}
	if (idept == 0) {
		isAll = true
		idept = 1
	} else if (idept >= Depts.length) {
		nextdept = -1
		showCourses()
		return
	}
	thisdept = idept
	if (isAll) {
		if (idept >= Depts.length){
			nextdept = 0
			extractClassLab()
			return
		}
		nextdept = idept + 1
	} else {
		theDept = Depts[idept][1].toLowerCase()
		nextdept = 0
	}
	var deptpage = Depts[idept][0]
	var url = classlabBase + searchyearterm + "/" + deptpage
	div("errors").innerHTML = "loading " + url
	if (Depts[idept][2]) {
		setTimeout('extractClassLabPage("")',10)
		return
	}
	loadXmlData(url, "", processClassLabPage, false)
}
var ClassLabCourses = []

var ClassLabNames2 = ["coursestatus","deptname","coursenumber",  
	"coursesection", "coursesubtype", "coursename","halfcredit", "credits", 
	"pn", "gereqs", "meetingtimes", "meetinglocations","instructors"]

function extractClassLabPage(info) {
	if (info.length > 500)
		Depts[thisdept][2] = info
	if (info.length == 0)
		info = Depts[thisdept][2]

/*
<tr class="sis-line1">
<td class="sis-Bcenter">C</td>
<td class="sis-Bleft">THEAT</td>
<td class="sis-Bleft"> 210 </td>
<td class="sis-Bleft">  </td>
<td class="sis-Bcourselab"> <span class="sis-help" title="Regular Course"> </span> </td>
<td class="sis-Bcoursename"> Plays & Playwrights
<td class="sis-Bcenter">  </td>
<td class="sis-Bcredits">1.00 </td>
<td class="sis-Bcenter">N</td>
<td class="sis-Bgereqs" nowrap>ALS-L<br>WRI </td>
<td class="sis-Bleft" nowrap>MWF 1045-1140 </td>
<td class="sis-Bleft" nowrap>RNS 356A </td>
<td class="sis-Binstructorname">Gisselman, Gary C. </td> </tr>
*/

	var S = info.split("sis-line1")
	for (var i = 1; i < S.length; i++) {
		var line = S[i]
		var c = ClassLabCourses[ClassLabCourses.length] = {}
		var Tags = getTagsByClassName(line, "td")
		for (var j = 0; j < ClassLabNames2.length; j++) {
			var name = ClassLabNames2[j]
			var s = Tags[j].replace(/\n/g," ")
			s = cleanData(s,"|")
			c[name] = s.split("|")
			if (c[name].length > 1 && name == "coursename") {
				c.notes = c[name]
				c[name] = c[name][0]
				c.notes[0] = ""
			}
		}
		c.fullcode = c.deptname + " " + c.coursenumber + c.coursesection + c.coursesubtype
	}

	if (nextdept) {
		loadClassLab(-nextdept)
	} else {
		getInfo()
	}


}


function showCourses(C, asbars) {


//	var s = ""
//	for (var i = 0; i < Depts.length; i++)s+=Depts[i][2]
//	div("resultDiv").innerHTML = s + s.replace(/\<tr/g,"@br><tr").replace(/\<td/g,"@br><td").replace(/\</g,"&lt;").replace(/\@br/g,"<br")
//
//	return


	var noC = !C
	if (noC)C = ClassLabCourses
	theseCourses = C
	showErrors(errors + C.length + (div("openonly").checked ? " OPEN" : "") + " courses for " + (theSearch ? '"' + theSearch + '" ':'') + theDept + " " + thisyearterm + " " + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href=javascript:showTabData()>tab-separated table</a>")
	var S = ""
	for (var i = 0; i < C.length; i++) {
		var c = C[i]
 		//for (var j in c)
		//	s += i + "\t"+ j + "\t" + C[i][j] + "\n"
		var td = "<td valign='top' " + (c.coursestatus == "C" ? "style='color:red'" : "") + " class='sis-lineX'>"
 		var s = "|" + td + c.deptname 
		+ "</td>" + td + " " + c.coursenumber + c.coursesection + ("LD".indexOf(c.coursesubtype) >= 0 ? c.coursesubtype : " ")
		+ "</td>" + td + c.coursename + "<br><font color=blue>" 
		+ c.gereqs + "</font> CR:" + c.credits + (c.pn == "Y" ? " P/N" : "") 
		+ (asbars ? "</td>" + td + getDayTimeTable(c.meetingtimes) : "")
		+ "</td>" + td + c.meetingtimes.join("<br>")
		+ "</td>" + td + c.meetinglocations.join("<br>")
		+ "</td>" + td + c.instructors.join("<br>")
		+ "</td>"
		c.lineinfo = s
		if (S.indexOf(s) < 0)
			S += s
	}
	S = S.split("|")
	for (var i = 0; i < S.length; i++)
		S[i] = S[i].replace(/lineX/g,"line" + ((i%2) + 1))
	S = S.join("</tr><tr>")
	div("resultDiv").innerHTML = "<table cellspacing='0' cellpadding='5'><tr>" + S +"</tr></table>"

	// known bug for mac: http://www.quirksmode.org/bugreports/archives/2005/05/Safari_13_visual_anomaly_with_windowlocationhref.html
	//alert(navigator.userAgent.toLowerCase().indexOf('safari'));

	//	if (navigator.userAgent.toLowerCase().indexOf('safari') == -1) {
	//		document.location.href = '#theresults';
	//	}
}


