// Pointers to program, course, location, schedule, and date dropdown
// elements.
var gcat;

// Program, course, location, schedule, or date dropdown INPUT may
// just have been updated.  Propagate any change to dependent fields.
function gcat_upd (input) {

    var next = input.selnext;
    if (!next)
	return;

    // Construct the next selector's option list.
    var selidx = input.hidden ? input.selidx : input.selectedIndex;
    var selopts;
    if (selidx <= 0)
	selopts = null;
    else {
	var optidx = (selidx - 1) * 2 + 1;
	selopts = input.selopts[optidx];
	if (!selopts) {

	    // Retrieve options from the server.
	    var post = ['type=' + next.postname];
	    var sels = gcat[input.formname].sels;
	    for (var i = 0; i < sels.length; i++) {
		var sel = sels[i];
		var selidx2 = sel.hidden ? sel.selidx : sel.selectedIndex;
		var id = sel.selopts[(selidx2 - 1) * 2];
		post.push(sel.postname + '=' + id);
		if (sel === input)
		    break;
	    }
	    post = post.join('&');
	    var chan = realed_xmlhttp_new();
	    chan.open("POST", "/reg/gcatget.php", false);
	    chan.setRequestHeader("Content-Type",
				  "application/x-www-form-urlencoded");
	    chan.send(post);
	    var replytxt = chan.responseText;
	    realed_xmlhttp_abort(chan);
	    var ids, clslst;
	    eval(replytxt);	// "ids = [<id>, <id2>, ...];"
	    selopts = new Array(ids.length * 2);
	    for (var i = 0, j = 0; i < ids.length; i++) {
		var id = ids[i];
		var child;
		if (id > 0)
		    child = null;
		else {
		    child = [id, [clslst[j], null]];
		    j += 2;
		}
		selopts[i * 2] = id;
		selopts[i * 2 + 1] = child;
	    }
	    input.selopts[optidx] = selopts;
	    if (clslst) {
		var vals = gcat_vals.date;
		for (var i = 0; i < clslst.length; i += 2)
		    vals[clslst[i]] = clslst[i + 1];
	    }
	}
    }
    if (input.prevselopts === selopts)
	return;
    input.prevselopts = selopts;
    var opts = [['', next.blank]];
    if (selopts) {
	var vals = gcat_vals[next.postname];
	for (var i = 0; i < selopts.length; i += 2) {
	    var id = selopts[i];
	    var val = typeof(id) != 'number' || id > 0 ? vals[id] :
		gcat_vals.media[-id];
	    opts.push([id, val]);
	}
    }

    // Choose the next selector's value.  During startup, use the previously
    // submitted value, if any.
    var nextval;
    if (next.initval === undefined)
	nextval = next.value;
    else {
	nextval = next.initval;

	// Explorer disallows "delete next.initval".
	next.initval = undefined;
    }

    // If the selector already has a nonzero value and the new option list
    // includes that value, use it.  Exception: when the previous value was
    // autoselected due to only one choice being available, don't autoselect
    // the same value if multiple choices are now available, to avoid
    // misleading the student into thinking that only the one choice is
    // available.
    var singleton = false;
    if (nextval && !input.singleton && selopts && selopts[nextval])
	;

    // Else if only one nonempty option exists, use it.
    else if (opts.length == 2) {
	nextval = opts[1][0];
	singleton = true;
    }

    // Otherwise, choose the empty option.
    else
	nextval = 0;
    input.singleton = singleton;

    // Overwrite the next selector's option list.
    var options = next.options;
    for (var i = 0; i < opts.length; i++) {
	var opt = opts[i];
	var optnode;
	if (i < options.length)
	    optnode = options[i];
	else {
	    optnode = options[0].cloneNode(true);
	    optnode.selected = false;
	    optnode.defaultSelected = false;
	    next.appendChild(optnode);
	}
	optnode.value = opt[0];
	optnode.firstChild.data = opt[1];
	if (opt[0] == nextval)
	    optnode.selected = true;
    }
    for (i = options.length; i > opts.length; i--)
	next.removeChild(options[i - 1]);

    // Work around Explorer bug that prevents above changes from showing up
    // immediately.
    if (!document.captureEvents) {
	var parent = next.parentNode;
	var sibling = next.nextSibling;
	parent.removeChild(next);
	if (sibling)
	    parent.insertBefore(next, sibling);
	else
	    parent.appendChild(next);
    }

    next.selopts = selopts;
    gcat_upd(next);
}

// onblur callback for search selection dropdowns.
function gcat_blur () {
    gcat_upd(this);
}

// onchange callback for search selection dropdowns.
function gcat_chg () {
    gcat_upd(this);
}

// Document onload callback to set up dynamic search selection dropdowns.
function gcat_startup () {
    gcat = {};

    // Retrieve information about the class lookup dropdowns on this page.
    var pairs = [['fast', false],
		 ['sched', true],
		 ['sched2', true]];
    for (var i = 0; i < pairs.length; i++) {
	var pair = pairs[i];
	var formname = pair[0];
	var proghide = pair[1];
	var names = ['prog', 'course', 'loc', 'sched', 'date'];
	var form = {};
	var sels = [];

	// Infer form presence or absence by the presence or absence of its
	// filter fields.
	var j, prev;
	for (j = 0; j < names.length; j++) {
	    var name = names[j];
	    var id = formname + '-' + name;
	    var input = document.getElementById(id);
	    if (!input)
		break;
	    input.formname = formname;
	    input.postname = name;
	    if (input.options) {
		input.blank = input.options[0].firstChild.data;
		input.selopts = null;
		input.prevselopts = null;
		input.onblur = gcat_blur;
		input.onchange = gcat_chg;
	    }
	    if (j)
		prev.selnext = input;
	    prev = input;
	    form[name] = input;
	    sels.push(input);
	}
	if (j < names.length)
	    continue;
	form.sels = sels;
	gcat[formname] = form;

	var prog = form.prog;
	prog.hidden = proghide;
	if (proghide) {
	    var progid = parseInt(prog.value);
	    for (var j = 0; j < gcat_tree.length; j += 2) {
		if (progid == gcat_tree[j]) {
		    prog.selidx = j / 2 + 1;
		    break;
		}
	    }
	}

	// Update the level dropdown to match the selected program.
	prog.selopts = gcat_tree;
	gcat_upd(prog);
    }
}

// Redirect to the enrollment page for the class selected in FORMNAME.
function gcat_submit (formname, savesrch) {
    var classid = gcat[formname].date.value;
    if (!classid)
	return;
    var url = "/reg/enroll.php?class=" + classid +
	'&savesrch=' + savesrch;
    window.location.href = url;
}

